Google Ads API is returning to beta status. Please read our blog post for more details.

检索对象

GoogleAdsService 是 Google Ads API 的统一对象检索和报告服务。该服务提供的搜索方法有如下特征:

  • 检索对象的特定属性。
  • 根据日期范围检索对象的效果指标。
  • 根据对象的属性执行对象排序。
  • 使用条件指示要在响应中返回的对象。
  • 使用分页功能,将较多的响应分为多个易于管理的结果页面。
  • 限制返回的对象数量。

发出请求

搜索方法需要 SearchGoogleAdsRequest,其中包含以下属性:

  • customer_id.
  • Google Ads 查询语言 query,用于指示要查询的资源,要检索的属性、细分和指标,以及用于限制返回哪些对象的条件。
  • page_size,用于在使用分页功能时指示单个响应中可返回的对象数量。
  • 可选的 page_token,用于在使用分页时检索下一批结果。

如需详细了解 Google Ads 查询语言,请参阅 Google Ads 查询语言指南

处理响应

GoogleAdsService 搜索请求会返回 SearchGoogleAdsResponse,其中包含以下属性:

  • GoogleAdsRow 对象的 results 集合。

  • total_results_count,用于指示与查询匹配的结果的总数,忽略 LIMIT 子句。

  • next_page_token,用于请求结果集中的下一批结果。

  • field_mask,用于指示您在查询的 SELECT 子句中请求了哪些字段。

将结果分页

Google Ads 查询语言通过在您的请求中指定 page_size 来支持分页。这会将查询的结果集分为多个响应,其中每个响应最多可包含 page_size 个对象。如果未指定 page_size,系统会自动将其设置为页面大小上限(即 10,000 个)。

以下面的查询为例:

SELECT ad_group.id, ad_group_criterion.type, ad_group_criterion.criterion_id,
       ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type
FROM ad_group_criterion
WHERE ad_group_criterion.type = KEYWORD

如果您的帐号包含 50,000 个关键字而 page_size 设置为 1,000,则结果集包含的将是第一个响应中的 1,000 个 GoogleAdsRow 对象,外加一个 next_page_token。要检索下一批 1,000 行,只需使用相同的页面大小设置再发送一次请求即可,不过要将请求中的 page_token 更新为前一响应的 next_page_token。在后续的每次请求中,page_size 的值可能都会不同。

我们的客户端库会自动处理分页。您只需遍历响应的行即可。在返回当前页面中的所有行后,客户端库会代表您自动获取新的行页面,直到检索了整个数据集为止。如果使用 REST 取代 gRPC,那么您必须对每个新的页面明确地发出请求。

Google Ads API 在内部缓存整个数据集,因此后续请求的速度会比第一个请求快。根据您的用例,您可以将 page_size 设置为 1 到 10,000 之间的任何值。一般来说,为了加快整体的性能速度,您应该使用较大的 page_size,因为可减少响应中的往返次数。

您的查询必须在后续请求中完全保持不变,才能利用缓存的数据;这些请求不会对您的配额产生影响,对于基本访问权限而言,尤其如此。但如果查询发生变化,并且是与页面令牌一起发送的,则会导致错误。当需要手动分页(例如在网页导航期间)时,您可以使用页面令牌一次检索一个页面,代码如下:

Java

try (GoogleAdsServiceClient googleAdsServiceClient = GoogleAdsServiceClient.create()) {
  int pageSize = 50;
  String customerId = "INSERT_CUSTOMER_ID_HERE";
  String query = "SELECT campaign.id, campaign.name FROM campaign";

  SearchGoogleAdsRequest request =
      SearchGoogleAdsRequest.newBuilder()
          .setCustomerId(customerId)
          .setPageSize(pageSize)
          .setQuery(query)
          .build();

  while (true) {
    SearchGoogleAdsResponse response = googleAdsServiceClient.searchCallable().call(request);
    for (GoogleAdsRow element : response.getResultsList()) {
      System.out.printf(
          "Campaign with ID %d and name '%s' was found.%n",
          element.getCampaign().getId().getValue(), element.getCampaign().getName().getValue());
    }

    String nextPageToken = response.getNextPageToken();
    if (!Strings.isNullOrEmpty(nextPageToken)) {
      request = request.toBuilder().setPageToken(nextPageToken).build();
    } else {
      break;
    }
  }

}

C#

private void PerPageLoopingExample(GoogleAdsClient client, long customerId)
{
  string query = "SELECT campaign.id, campaign.name FROM campaign";

  string pageToken = null;
  const int PAGE_SIZE = 20;

  do
  {
    pageToken = ProcessAPage(client, customerId.ToString(), query,
      PAGE_SIZE, pageToken);
  }
  while (pageToken != null);
}

private string ProcessAPage(GoogleAdsClient client, string customerId, string query,
  int pageSize, string pageToken)
{
  // Get the GoogleAdsService.
  GoogleAdsServiceClient googleAdsService = client.GetService(
    Services.V1.GoogleAdsService);

  // Create a SearchGoogleAdsRequest for the query.
  SearchGoogleAdsRequest request = new SearchGoogleAdsRequest()
  {
    Query = query,
    PageSize = pageSize,
    CustomerId = customerId,
  };

  // If a pageToken is not provided, a fresh query will run on the server.
  if (pageToken != null)
  {
    request.PageToken = pageToken;
  }

  // Issue a search request.
  IEnumerable response =
    googleAdsService.Search(request).AsRawResponses();

  // Obtain the first page.
  SearchGoogleAdsResponse currentResponse = response.FirstOrDefault();

  // Process the results.
  foreach (GoogleAdsRow row in currentResponse.Results)
  {
    Console.WriteLine($"{row.Campaign.Id}, {row.Campaign.Name}");
  }

  // Store the next page token for retrieving the next page in the future.
  return currentResponse.NextPageToken;
}

PHP

$pageSize = 50;
$customerId = 'INSERT_CUSTOMER_ID_HERE';
$query = 'SELECT campaign.id, campaign.name FROM campaign';
$nextPageToken = null;

while (true) {
    $response = $googleAdsServiceClient->search($customerId, $query,
        ['pageSize' => $pageSize, 'pageToken' => $nextPageToken]);

    $page = $response->getPage();
    foreach ($page as $element) {
        printf(
            "Campaign with ID %d and name '%s' was found.%s",
            $element->getCampaign()->getId()->getValue(),
            $element->getCampaign()->getName()->getValue(),
            PHP_EOL
        );
    }

    if (empty($page->getNextPageToken())) {
        break;
    } else {
        $nextPageToken = $page->getNextPageToken();
    }
}

理解 GoogleAdsRow

GoogleAdsRow 表示相关查询所返回的对象,由一组根据 SELECT 子句中请求的字段填充的属性组成。

例如,上述条件查询的响应将包含一系列 GoogleAdsRow 对象,其中填充了以下属性:

ad_group
  id
ad_group_criterion
  type
  criterion_id
  keyword
    text
    match_type

例如,虽然 ad_group_criterion 具有 status 属性,但在上述查询的响应中,不会填充该行的 ad_group_criterion 属性的 status 字段,这是因为 SELECT 子句不包含 ad_group_criterion.status。同样,也不会填充该行的 campaign 属性,因为 SELECT 子句不包含来自 campaign 资源的任何字段。

细分

对于包含以下各项的每种组合,响应均将包含一个 GoogleAdsRow

  • FROM 子句中指定的主要资源的实例
  • 每个选定的 segment 字段的值

例如,对于包含以下各项的每种组合,如果一个查询选择了 FROM campaign 并且 SELECT 子句中包含 segments.ad_network_typesegments.date,那么该查询的响应将包含一个 GoogleAdsRow 行:

  • campaign
  • segments.ad_network_type
  • segments.date