构建响应

应用处理完来自 Google 的出价请求后,必须构建并发送响应。本指南介绍了如何编写应用代码来构建响应。

创建 BidResponse 消息

如需提交出价,您的出价应用必须使用包含 Bid 的 BidResponse(采用您配置的格式)来响应出价请求。如果您使用的是 JSON 格式,则响应必须将 Content-Type 标头设置为 application/json; charset=utf-8,并在正文中包含 JSON BidResponse。如果您使用的是 Protobuf 格式,则应用必须将 Content-Type 标头设置为 application/octet-stream,并在正文中包含序列化的 BidResponse。

如需为 Protobuf 格式构建和序列化 BidResponse,您必须根据 openrtb.proto 和 openrtb-adx.proto 生成并使用 Protobuf 库,它们分别在 Protobuf 中实现标准 OpenRTB BidResponse 字段和 Google 扩展。这些内容可在原型和参考数据中找到。

如果您不想对某次展示出价,则必须返回空的 HTTP 204 响应。您的应用必须针对每个 BidRequest 返回响应。超时和无法解析的响应会被视为错误,Google 会对错误率较高的出价方进行限制。

广告素材 ID

您的 BidResponse 通过 BidResponse.seatbid.bid.crid 字段(128 字节限制)指定广告素材。即使是相似的广告素材,如果它们在任何显著特征(包括但不限于尺寸、声明的网址、广告素材属性和供应商类型)上存在差异,也必须为此字段设置唯一值。换句话说,您必须为满足以下条件的任意两个广告指定不同的广告素材 ID:

  • 外观或行为不同。
  • 渲染到不同的图片。
  • 以不同的方式呈现(例如,一个广告由图片组成,而另一个广告是视频)。

在设计应用时,您应确定一种系统化的标识符生成方式,这种方式应适合您计划提交的广告素材类型。

广告属性

Google 建议您结合使用 BidResponse.seatbid.bid.apis 和 BidResponse.seatbid.bid.attr,或使用 BidResponse.seatbid.bid.ext.attribute 扩展程序来声明广告素材属性,以描述广告的特征及其定位。下面介绍了如何声明属性:

  • VPAID
    将 BidResponse.seatbid.bid.apis 设置为 VPAID_1 或 VPAID_2。对于 JSON 格式,可以分别将其设置为 1 或 2。
  • MRAID
    将 BidResponse.seatbid.bid.apis 设置为 MRAID_1,或将 3 设置为 JSON 格式。
  • SIZELESS
    将 BidResponse.seatbid.bid.attr 设置为 RESPONSIVE,或将 18 设置为 JSON 格式。
  • PLAYABLE
    这可以通过将 BidResponse.seatbid.bid.attr 设置为 USER_INTERACTIVE 或 13(对于 JSON 格式)来表示。

如需了解如何获取有关广告素材检测到的属性的反馈,请参阅广告素材资源。

公开出价字段

参与公开出价的广告交易平台和广告联盟出价方发送的出价响应与参与标准实时出价的 Authorized Buyers 买方发送的出价响应类似。公开出价客户可以指定少量其他字段,并且一些现有字段可能有其他用途。这些情况包括:

字段 详细信息
BidResponse.imp.pmp.deals.id

来自广告交易平台命名空间的交易 ID,该 ID 与此出价相关联,并会报告给发布商。

BidResponse.seatbid.bid.ext.exchange_deal_type

向发布商报告的交易类型,会影响交易在竞价中的处理方式。

BidResponse.seatbid.bid.ext.third_party_buyer_token 如果作为公开出价方的广告交易平台是中介,则使用令牌来标识最终第三方买方信息。此令牌是从第三方买方处获取的,必须在出价响应中原封不动地传递给 Google。

建议

  • 在服务器上启用持久 HTTPS 连接(也称为“keep-alive”或“连接重用”)。将超时时间设置为至少 10 秒,在许多情况下,设置更长的超时时间会更有利。Google 会在应用的初始延迟时间测试期间验证这一点,因为 Authorized Buyers 会以较高的速率发送请求,并且需要避免为每个请求建立单独的 TCP 连接所产生的延迟时间开销。
  • 添加可选的展示跟踪网址,以便在展示呈现时(而非出价方胜出时)进行跟踪。由于胜出和呈现之间存在流失,因此这种方法可以产生更准确的跟踪统计信息。

  • 请确保您的出价工具代码不依赖于已弃用的字段,否则可能会导致出价失败并出现错误。
  • 在 BidResponse 中添加 BidResponse.seatbid.bid.w 和 BidResponse.seatbid.bid.h。针对包含多种广告尺寸的请求,BidResponse 必须包含这些字段,否则将无法参与竞价。
  • 将回答大小限制在 8K 以下。非常大的响应可能会增加网络延迟时间并导致超时。
  • 遵循针对需要 SKAdNetwork 归因的 iOS 广告资源的出价指南。

出价响应示例

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

OpenRTB Protobuf

OpenRTB JSON

重要提示:示例中描述的 Protobuf 消息在此处以人类可读的文本形式表示。不过,这并不是消息通过网络发送的方式。使用 OpenRTB Protobuf 格式时,系统仅接受序列化的 BidResponse 消息。

您可以使用以下 C++ 代码创建和序列化 BidResponse 消息:

BidResponse bid_response;
// fill in bid response with bid information
string post_response;
if (bid_response.SerializeToString(&post_response)) {
  // respond to the POST with post_response as the content
} else {
  // return an error to the POST
}

指定广告素材

您的出价响应会指定在您的出价胜出时要投放的广告素材。您的出价必须包含一种受支持的广告格式(AMP、视频、原生)。在此示例中,我们使用 html_snippet 字段指定广告素材。

或者,您也可以根据广告格式,使用以下一个字段指定广告素材:

  • SDK 呈现的广告
    • BidResponse.seatbid.bid.ext.sdk_rendered_ad
  • AMP
    • BidResponse.seatbid.bid.amp_ad_url
  • 视频
    • BidResponse.seatbid.bid.adm
  • 原生广告
    • BidResponse.seatbid.bid.adm_native

使用 BidResponse.seatbid.bid.adm 字段中的 HTML 代码段指定托管在您自己的服务器上的广告。该代码段封装在插入到网页中的 iFrame 内,这样,当网页加载时,系统就会检索并呈现广告。您必须精心制作 HTML 代码段,以便广告(横幅广告或插页式广告)在 iFrame 中正确呈现,并以适当的尺寸呈现在您出价的广告位中。

此外,在以下情况下,出价响应中声明的广告尺寸必须与出价请求中的某个尺寸组合完全一致:

  • 广告是常规横幅广告(非视频广告、原生广告或插页式广告)。
  • 出价方已在出价响应中声明尺寸。只要请求中存在多个尺寸,就必须声明尺寸。
  • 插页式广告属于例外情况。对于插页式广告,宽度必须至少为屏幕宽度的 50%,高度必须至少为屏幕高度的 40%。

您可以使用任何可正确呈现的有效 HTML 代码来指定 HTML 代码段广告素材,但请注意创建 BidResponse 消息部分中有关指定 crid 字段的限制。此功能的一种用途是将额外信息放入从服务器提取的网址的参数中,作为呈现广告的一部分。这样,您就可以将有关展示的任意数据传回自己的服务器。

对于出价响应中返回的 HTML 代码段,大多数政策都与第三方广告相同。如需了解详情,请参阅 Authorized Buyers 计划指南、第三方广告投放要求和在广告中声明点击后到达网址。

使用一致的点击后到达网址

您在 BidResponse.seatbid.bid.ext.clickurl 字段中指定的点击后到达网址必须与广告素材中指定的着陆页网址完全相同。以下是采用支持的格式且与设置为 https://play.google.com/store/apps/details?id=com.example.myawesomeapp&referrer=utm_source%3Dgoogle_ab%26utm_medium%3Dcpc%26utm_campaign%3Dinstall_campaign_1 的 clickurl 字段一致的广告素材示例:

HTML

<div id="my-app-install-ad"
     style="font-family: sans-serif; border: 1px solid #ddd; padding: 10px;
            display: flex; align-items: center; width: 100%; height: 100%;
            box-sizing: border-box; cursor: pointer;"
     onclick="window.open('https://play.google.com/store/apps/details?id=com.example.myawesomeapp&referrer=utm_source%3Dgoogle_ab%26utm_medium%3Dcpc%26utm_campaign%3Dinstall_campaign_1', '_blank')">
  <img src="https://example.com/path/to/app_icon.png" alt="App Icon"
       style="width: 60px; height: 60px; margin-right: 10px;
              border-radius: 8px;">
  <div style="flex-grow: 1;">
    <h4 style="margin: 0 0 5px 0; font-size: 16px; color: #1a73e8;">
      My Awesome App
    </h4>
    <p style="margin: 0 0 10px 0; font-size: 14px; color: #5f6368;">
      The best app for doing awesome things! Download now and get started!
    </p>
    <span style="background-color: #1a73e8; color: white; padding: 8px 12px;
                 text-align: center; text-decoration: none;
                 display: inline-block; border-radius: 4px; font-size: 14px;
                 font-weight: bold;">Install</span>
  </div>
</div>

VAST XML

<VAST version="3.0">
  <Ad id="creative_id_789">
    <InLine>
      <AdSystem>MyBidderSystem</AdSystem>
      <AdTitle>My Awesome App Install Video</AdTitle>
      <Description>Install My Awesome App now!</Description>
      <Error>
        <![CDATA[https://tracking.example.com/vast_error?errorcode=[ERRORCODE]]]>
      </Error>
      <Impression>
        <![CDATA[https://tracking.example.com/vast_impression]]>
      </Impression>
      <Creatives>
        <!-- Main Video Creative -->
        <Creative>
          <Linear>
            <Duration>00:00:15</Duration>
            <TrackingEvents>
              <Tracking event="start">
                <![CDATA[https://tracking.example.com/vast_event?label=start]]>
              </Tracking>
              <Tracking event="firstQuartile">
                <![CDATA[https://tracking.example.com/vast_event?label=firstQuartile]]>
              </Tracking>
              <Tracking event="midpoint">
                <![CDATA[https://tracking.example.com/vast_event?label=midpoint]]>
              </Tracking>
              <Tracking event="thirdQuartile">
                <![CDATA[https://tracking.example.com/vast_event?label=thirdQuartile]]>
              </Tracking>
              <Tracking event="complete">
                <![CDATA[https://tracking.example.com/vast_event?label=complete]]>
              </Tracking>
            </TrackingEvents>
            <VideoClicks>
              <ClickThrough id="gplay-video">
                <![CDATA[https://play.google.com/store/apps/details?id=com.example.myawesomeapp&referrer=utm_source%3Dgoogle_ab%26utm_medium%3Dcpc%26utm_campaign%3Dinstall_campaign_1]]>
              </ClickThrough>
              <ClickTracking id="bidder-tracker-video">
                <![CDATA[https://tracking.example.com/vast_click]]>
              </ClickTracking>
            </VideoClicks>
            <MediaFiles>
              <MediaFile delivery="progressive" type="video/mp4" width="640"
                         height="360" bitrate="800" scalable="true"
                         maintainAspectRatio="true">
                <![CDATA[https://cdn.example.com/myawesomeapp_video.mp4]]>
              </MediaFile>
            </MediaFiles>
          </Linear>
        </Creative>
        <!-- Companion Ad Creative -->
        <Creative>
          <CompanionAds>
            <Companion id="companion1" width="300" height="250"
                       assetWidth="300" assetHeight="250">
              <StaticResource creativeType="image/png">
                <![CDATA[https://cdn.example.com/companion_banner_300x250.png]]>
              </StaticResource>
              <TrackingEvents>
                <Tracking event="creativeView">
                  <![CDATA[https://tracking.example.com/vast_companion_view]]>
                </Tracking>
              </TrackingEvents>
              <CompanionClickThrough>
                <![CDATA[https://play.google.com/store/apps/details?id=com.example.myawesomeapp&referrer=utm_source%3Dgoogle_ab%26utm_medium%3Dcpc%26utm_campaign%3Dinstall_campaign_1]]>
              </CompanionClickThrough>
              <CompanionClickTracking>
                <![CDATA[https://tracking.example.com/vast_companion_click]]>
              </CompanionClickTracking>
            </Companion>
          </CompanionAds>
        </Creative>
      </Creatives>
    </InLine>
  </Ad>
</VAST>

原生

{
  "ver": "1.2",
  "assets": [
    {
      "id": 1,
      "title": {
        "text": "My Awesome App"
      }
    },
    {
      "id": 2,
      "img": {
        "url": "https://example.com/path/to/app_icon.png",
        "w": 60,
        "h": 60
      }
    },
    {
      "id": 3,
      "data": {
        "value":
          "The best app for doing awesome things! Download now and get started!"
      }
    },
    {
      "id": 4,
      "data": {
        "value": "Install"
      }
    }
  ],
  "link": {
    "url": "https://play.google.com/store/apps/details?id=com.example.myawesomeapp&referrer=utm_source%3Dgoogle_ab%26utm_medium%3Dcpc%26utm_campaign%3Dinstall_campaign_1",
    "clicktrackers": [
      "https://tracking.example.com/native_click"
    ]
  },
  "imptrackers": [
    "https://tracking.example.com/native_impression"
  ]
}

指定宏

宏是嵌入到某些包含网址的出价响应字段中的格式化文本,在广告投放时会被替换为相关值。例如,如果您的胜出出价在出价中包含的 HTML 代码段广告素材中包含 AUCTION_PRICE 宏,则该宏将被替换为一个值,您可以解密该值,以确定您在竞价中为展示支付的金额。

您可以在以下字段中添加宏:

  • BidResponse.seatbid.bid.adm

    HTML 代码段、原生、视频网址和视频 VAST XML 格式支持宏。

  • BidResponse.seatbid.bid.adm_native.eventtrackers.url

  • BidResponse.seatbid.bid.adm_native.imptrackers

  • BidResponse.seatbid.bid.ext.amp_ad_url

    AMP 广告素材仅支持 Google 专用的 WINNING_PRICE 和 WINNING_PRICE_ESC 宏。

  • BidResponse.seatbid.bid.burl

  • BidResponse.seatbid.bid.ext.impression_tracking_url

    如果您需要多个结算网址,请使用此字段,而不是 BidResponse.seatbid.bid.burl。

例如,您可以在用于提取广告素材的网址中嵌入 ${MACRO},从而将宏作为 HTML 代码段的一部分,其中 MACRO 是 OpenRTB 规范中所述的一种受支持的宏。

Google 宏

除了 OpenRTB 规范中提供的宏之外,Google 还支持其他宏。这些宏的格式不同,如果嵌入到网址中,则会显示为 %%MACRO%%。下表介绍了这些宏:

微距 说明
ADVERTISING_IDENTIFIER 允许买方在展示广告时接收 iOS IDFA 或 Android 广告 ID。 如需了解详情,请参阅解密广告客户标识符。
CACHEBUSTER 随机、无符号、四字节整数的字符串表示法。
CLICK_URL_UNESC

广告的不转义点击跟踪网址。在代码段中,第三方点击跟踪网址的转义版本应紧跟在宏后面。

例如,如果第三方点击跟踪网址为 http://my.adserver.com/some/path/handleclick?click=clk,则可将以下代码与宏调用后经过单重转义的第三方点击跟踪网址搭配使用:

<a href="%%CLICK_URL_UNESC%%http%3A%2F%2Fmy.adserver.com%2Fsome%2Fpath%2Fhandleclick%3Fclick%3Dclk"></a>

在广告投放时,此宏会展开为:

<a href="http://google-click-url?...&ad_url=http%3A%2F%2Fmy.adserver.com%2Fsome%2Fpath%2Fhandleclick%3Fclick%3Dclk"></a>

该网址会先向 Google 注册点击,然后重定向到第三方点击跟踪网址。

CLICK_URL_ESC

广告的转义点击跟踪网址。如果您需要先将值传递到另一个随后会返回重定向的服务器,请使用此宏而非 CLICK_URL_UNESC。

例如,以下代码可用于 HTML 代码段:

<a href="http://my.adserver.com/click?google_click_url=%%CLICK_URL_ESC%%"></a>

在广告投放时,此宏会展开为:

<a href="http://my.adserver.com/click?google_click_url=http://google-click- url%3F...%26ad_url%3D"></a>

这会将点击注册到 my.adserver.com,然后由其负责重定向到 google_click_url 参数中传递的网址。这假设 my.adserver.com 会对 google_click_url 参数进行反转义。

您可以在 %%CLICK_URL_ESC%% 后面附加一个经过双重转义的网址。my.adserver.com 完成反转义后,系统会将经过单次转义的网址版本附加到 google_click_url。提取 google_click_url 时,它会再次取消转义,然后重定向。

CLICK_URL_ESC_ESC

经过两次转义的广告网址。如果您需要先将值传递到另一个随后会返回重定向的服务器,请使用此宏而非 CLICK_URL_UNESC。

例如,以下代码可用于 HTML 代码段:

<a href="http://my.adserver.com/click?google_click_url=%%CLICK_URL_ESC_ESC%%"></a>

在广告投放时,此宏会展开为:

<a href="http://my.otheradserver.com/click?google_click_url=http%3A%2F%2Fmy.adserver.com%2Fclick%3Fgoogle_click_url%3Dhttp%3A%2F%2Fgoogle-click-%20url%253F...%2526ad_url%253D"></a>
SCHEME 如果出价请求不需要 SSL,则展开为 http:;如果出价请求需要 SSL,则展开为 https:。
SITE 内容网址的域名(经过了网址转义)或匿名广告资源的匿名 ID。
SITE_URL 已弃用。已被 SITE 宏取代,后者提供相同的功能。
TZ_OFFSET 时区偏移量。
VERIFICATION

生产环境和在验证流水线中扫描广告素材时的不同值。格式为:%%?VERIFICATION:true-val:false-val%%,其中 true-val 和 false-val 可以使用除宏以外的任何值,包括空字符串。对于公开出价,我们建议广告交易平台使用此宏;一旦他们这样做,需求方平台就无需进行更改。

例如,如果广告素材包含 %%?VERIFICATION:-1:5000%%,则在投放时文本替换为 5000,在验证流水线中替换为 -1。这有助于区分这两组 ping。

WINNING_PRICE

编码格式的展示费用(即 CPI,而不是每千次展示费用),以账号币种的百万分之一表示。例如,以 5 美元赢得的每千次展示费用出价相当于 5 百万个每千次展示费用出价宏,或者 5000 个 CPI 宏。在这种情况下,WINNING_PRICE 的解码值将为 5,000。 胜出价格是以 CPI 指定的。

要解析此宏,您需要实现一个可解密价格确认信息的应用。如需了解详情,请参阅解密价格确认信息页面。

WINNING_PRICE_ESC 经过网址转义的 WINNING_PRICE。

Google 要求您在第三方投放的广告的广告素材中使用 CLICK_URL_UNESC 或 CLICK_URL_ESC 宏。Google 使用 CLICK_URL 宏进行点击跟踪。

宏中的网址转义使用以下方案:

  • 空格字符会被替换为加号 (+)。
  • 字母数字字符(0-9、a-z、A-Z)和字符集 !()*,-./:_~ 中的字符保持不变。
  • 所有其他字符都会替换为 %XX,其中 XX 是表示该字符的十六进制数字。

发布商限制和要求

出价请求包含有关发布商对竞价中的广告素材施加的限制和要求的类型的信息。

  • BidRequest.bcat
    • 您可以使用 Real-time Bidding API 的 detectedCategories 字段,将此字段指定的被屏蔽类别与为提交的广告素材检测到的类别进行比较。
  • BidRequest.imp.ext.allowed_vendor_type
  • BidRequest.imp.secure
    • 在实践中,此字段将始终设置为 true,因为 Google 要求所有广告素材都支持 SSL。
  • BidRequest.imp.{audio/banner/native/video}
  • BidRequest.imp.{audio/banner/native/video}.api
  • BidRequest.imp.{audio/banner/native/video}.battr
  • BidRequest.imp.{audio/banner/video}.mimes

切勿使用包含受限功能的广告进行出价。对于允许的功能(例如供应商类型),仅当广告的供应商类型位于 BidRequest 的 allowed_vendor_type 列表中时,才返回该广告。您的出价中应仅包含通过填充 BidRequest.imp.banner 等字段在出价请求中指定的广告格式。如需了解详情,请参阅 BidRequest 协议缓冲区定义中这些字段的注释。

如果 BidResponse 中返回了广告,您必须在 BidResponse 中准确设置 BidResponse.seatbid.bid.attr、BidResponse.seatbid.bid.cat 以及 BidResponse.seatbid.bid.adomain 或 BidResponse.seatbid.bid.adm_native.link.url 字段。如果广告有多个适用于这些字段的值,则您必须添加每个值。如需了解详情,请参阅 BidResponse 协议缓冲区定义中有关这些字段的注释。 未设置这些字段的响应会被舍弃。

开放式衡量

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

支持的广告格式包括视频广告、横幅广告和插页式广告。如需详细了解如何在包含这些格式的出价响应中使用 Open Measurement,请参阅 Open Measurement SDK 帮助中心文章。

出价响应示例

以下部分展示了不同广告类型的出价响应示例。

应用横幅广告

OpenRTB Protobuf

OpenRTB JSON

应用插页式广告

OpenRTB Protobuf

OpenRTB JSON

应用插页式视频广告

OpenRTB Protobuf

OpenRTB JSON

应用原生广告

OpenRTB Protobuf

OpenRTB JSON

网络视频

OpenRTB Protobuf

OpenRTB JSON

移动网站横幅广告(适用于广告交易平台出价功能)

OpenRTB Protobuf

OpenRTB JSON