生成报告

您可以使用 Ad Manager API 创建互动式报告、运行现有报告,以及读取报告结果。

如果您不熟悉 Ad Manager 中的互动式报告,请参阅创建互动式报告,概览如何在 Ad Manager 界面中使用互动式报告。

对于复杂的报告,您可以使用 Ad Manager 界面来检查维度和指标的兼容性。所有界面报告都可以通过 API 运行。

本指南介绍了如何启动 Report 的异步运行、轮询返回的 Operation 状态、从已完成的 Operation 获取 Result 资源名称,以及提取分页结果集 Rows

前提条件

在继续之前,请确保您有权访问 Google Ad Manager 广告资源网。如需获取访问权限,请参阅 Google Ad Manager 使用入门

运行报告

若要生成报告,您需要知道相应报告的 ID。您可以在 Ad Manager 界面中通过报告网址获取报告 ID。例如,在网址 https://www.google.com/admanager/234093456#reports/interactive/detail/report_id=4555265029 中,报告 ID 为 4555265029

您还可以使用 networks.reports.list 方法读取用户有权访问的报告,并从资源名称中获取 ID:

networks/234093456/reports/4555265029

获取报告 ID 后,您可以使用 networks.reports.run 方法启动报告的异步运行。此方法会返回长时间运行的 Operation 的资源名称。请注意,在以下示例代码中,[REPORT] 是报告 ID 的占位符,[NETWORK] 是广告联盟代码的占位符。如需查找您的广告资源网代码,请参阅查找 Ad Manager 账号信息

Java

import com.google.ads.admanager.v1.ReportName;
import com.google.ads.admanager.v1.ReportServiceClient;
import com.google.ads.admanager.v1.RunReportResponse;

public class SyncRunReportReportname {

  public static void main(String[] args) throws Exception {
    syncRunReportReportname();
  }

  public static void syncRunReportReportname() throws Exception {
    try (ReportServiceClient reportServiceClient = ReportServiceClient.create()) {
      ReportName name = ReportName.of("[NETWORK_CODE]", "[REPORT]");
      RunReportResponse response = reportServiceClient.runReportAsync(name).get();
    }
  }
}

Python

from google.ads import admanager_v1


def sample_run_report():
    # Create a client
    client = admanager_v1.ReportServiceClient()

    # Initialize request argument(s)
    request = admanager_v1.RunReportRequest(
        name="networks/[NETWORK_CODE]/reports/[REPORT]",
    )

    # Make the request
    operation = client.run_report(request=request)

    print("Waiting for operation to complete...")

    response = operation.result()

    # Handle the response
    print(response)

.NET

using Google.Ads.AdManager.V1;
using Google.LongRunning;

public sealed partial class GeneratedReportServiceClientSnippets
{
    public void RunReportResourceNames()
    {
        // Create client
        ReportServiceClient reportServiceClient = ReportServiceClient.Create();
        // Initialize request argument(s)
        ReportName name = ReportName.FromNetworkCodeReport("[NETWORK_CODE]", "[REPORT]");
        // Make the request
        Operation<RunReportResponse, RunReportMetadata> response = reportServiceClient.RunReport(name);

        // Poll until the returned long-running operation is complete
        Operation<RunReportResponse, RunReportMetadata> completedResponse = response.PollUntilCompleted();
        // Retrieve the operation result
        RunReportResponse result = completedResponse.Result;

        // Or get the name of the operation
        string operationName = response.Name;
        // This name can be stored, then the long-running operation retrieved later by name
        Operation<RunReportResponse, RunReportMetadata> retrievedResponse = reportServiceClient.PollOnceRunReport(operationName);
        // Check if the retrieved long-running operation has completed
        if (retrievedResponse.IsCompleted)
        {
            // If it has completed, then access the result
            RunReportResponse retrievedResult = retrievedResponse.Result;
        }
    }
}

cURL

请求

curl -X POST -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"https://admanager.googleapis.com/v1/networks/${NETWORK_CODE}/reports/{$REPORT_ID}:run"

响应

{
  "name": "networks/234093456/operations/reports/runs/6485392645",
  "metadata": {
    "@type": "type.googleapis.com/google.ads.admanager.v1.RunReportMetadata",
    "report": "networks/234093456/reports/4555265029"
  }
}

轮询报告状态

如果您使用的是客户端库,上一部分的示例代码会按照建议的时间间隔轮询报告运行状态 Operation,并在报告生成完毕时提供结果。如需详细了解建议的轮询间隔,请参阅 networks.reports.run

如果您想更好地控制轮询,请使用 networks.operations.reports.runs.get 方法发出单独的请求,以检索正在运行的报告的当前状态:

Java

import com.google.ads.admanager.v1.ReportServiceSettings;
import com.google.api.gax.longrunning.OperationalTimedPollAlgorithm;
import com.google.api.gax.retrying.RetrySettings;
import com.google.api.gax.retrying.TimedRetryAlgorithm;
import java.time.Duration;

public class SyncRunReport {

  public static void main(String[] args) throws Exception {
    syncRunReport();
  }

  public static void syncRunReport() throws Exception {
    ReportServiceSettings.Builder reportServiceSettingsBuilder = ReportServiceSettings.newBuilder();
    TimedRetryAlgorithm timedRetryAlgorithm =
        OperationalTimedPollAlgorithm.create(
            RetrySettings.newBuilder()
                .setInitialRetryDelayDuration(Duration.ofMillis(500))
                .setRetryDelayMultiplier(1.5)
                .setMaxRetryDelayDuration(Duration.ofMillis(5000))
                .setTotalTimeoutDuration(Duration.ofHours(24))
                .build());
    reportServiceSettingsBuilder
        .createClusterOperationSettings()
        .setPollingAlgorithm(timedRetryAlgorithm)
        .build();
  }
}

Python

from google.ads import admanager_v1
from google.longrunning.operations_pb2 import GetOperationRequest

def sample_poll_report():
# Run the report
client = admanager_v1.ReportServiceClient()
response = client.run_report(name="networks/[NETWORK_CODE]/reports/[REPORT_ID]")

# Check if the long-running operation has completed
operation = client.get_operation(
    GetOperationRequest(name=response.operation.name))
if(operation.done):
    # If it has completed, then access the result
    run_report_response = admanager_v1.RunReportResponse.deserialize(payload=operation.response.value)

.NET

Operation<RunReportResponse, RunReportMetadata> retrievedResponse =
  reportServiceClient.PollOnceRunReport(operationName);
// Check if the retrieved long-running operation has completed
if (retrievedResponse.IsCompleted)
{
  // If it has completed, then access the result
  RunReportResponse retrievedResult = retrievedResponse.Result;
}

cURL

请求

curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"https://admanager.googleapis.com/v1/networks/${NETWORK_CODE}/operations/reports/runs/${OPERATION_ID}"

响应

{
  "name": "networks/234093456/operations/reports/runs/6485392645",
  "metadata": {
    "@type": "type.googleapis.com/google.ads.admanager.v1.RunReportMetadata",
    "percentComplete": 50,
    "report": "networks/234093456/reports/4555265029"
  },
  "done": false,
}

获取结果资源名称

报告运行 Operation 完成后,其中会包含 Result 的资源名称。

Java

RunReportResponse response = reportServiceClient.runReportAsync(name).get();
// Result name in the format networks/[NETWORK_CODE]/reports/[REPORT_ID]/results/[RESULT_ID]
String resultName = response.getReportResult();

Python

operation = client.run_report(request=request)
response = operation.result()
# Result name in the format networks/[NETWORK_CODE]/reports/[REPORT_ID]/results/[RESULT_ID]
result_name = response.report_result

.NET

Operation<RunReportResponse, RunReportMetadata> response = reportServiceClient.RunReport(request);
// Poll until the returned long-running operation is complete
Operation<RunReportResponse, RunReportMetadata> completedResponse = response.PollUntilCompleted();
RunReportResponse result = completedResponse.Result;
// Result name in the format networks/[NETWORK_CODE]/reports/[REPORT_ID]/results/[RESULT_ID]
string resultName = result.ReportResult;

cURL

请求

curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"https://admanager.googleapis.com/v1/networks/${NETWORK_CODE}/operations/reports/runs/${OPERATION_ID}"

响应

{
  "name": "networks/234093456/operations/reports/runs/6485392645",
  "metadata": {
    "@type": "type.googleapis.com/google.ads.admanager.v1.RunReportMetadata",
    "percentComplete": 100,
    "report": "networks/234093456/reports/4555265029"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.ads.admanager.v1.RunReportResponse",
    "reportResult": "networks/234093456/reports/4555265029/results/7031632628"
  }
}

读取结果行

Result 资源只有一个方法(networks.reports.results.fetchRows),用于读取分页行列表。每行包含一个维度值列表和一个分组指标值列表。每个组都包含指标值和任何比较值或标志。如需详细了解标记,请参阅在互动式报告中使用标记

对于不进行日期范围比较或拆分报告,系统会显示一个包含报告整个日期范围的指标值(例如展示次数或点击次数)的 MetricValueGroup

维度值和指标值的顺序与 ReportReportDefinition 中的顺序相同。

以下是 ReportDefinition 和相应 fetchRows 响应的 JSON 示例:

{
  "name": "networks/234093456/reports/4555265029",
  "visibility": "SAVED",
  "reportId": "4555265029",
  "reportDefinition": {
     "dimensions": [
      "LINE_ITEM_NAME",
      "LINE_ITEM_ID"
    ],
    "metrics": [
      "AD_SERVER_IMPRESSIONS"
    ], 
    "currencyCode": "USD",
    "dateRange": {
      "relative": "YESTERDAY"
    },
    "reportType": "HISTORICAL"
  },
  "displayName": "Example Report",
  "updateTime": "2024-09-01T13:00:00Z",
  "createTime": "2024-08-01T02:00:00Z",
  "locale": "en-US",
  "scheduleOptions": {}
}
{
  "rows": [
    {
      "dimensionValues": [
        {
          "stringValue": "Line Item #1"
        },
        {
          "intValue": "6378470710"
        }
      ],
      "metricValueGroups": [
        {
          "primaryValues": [
            {
              "intValue": "100"
            }
          ]
        }
      ]
    },
    {
      "dimensionValues": [
        {
          "stringValue": "Line Item #2"
        },
        {
          "intValue": "5457147368"
        }
      ],
      "metricValueGroups": [
        {
          "primaryValues": [
            {
              "intValue": "95"
            }
          ]
        }
      ]
    }
],
"runTime": "2024-10-02T10:00:00Z",
  "dateRanges": [
    {
      "startDate": {
        "year": 2024,
        "month": 10,
        "day": 1
      },
      "endDate": {
        "year": 2024,
        "month": 10,
        "day": 1
      }
    }
  ],
  "totalRowCount": 2
}

如果您使用的是客户端库,则响应中会包含一个迭代器,用于延迟请求其他网页。您还可以使用 pageTokenpageSize 参数。如需详细了解这些参数,请参阅查询参数。如果存在其他页面,响应中会包含一个 nextPageToken 字段,其中包含要在下一个请求中使用的令牌。

Java



import com.google.ads.admanager.v1.Report;
import com.google.ads.admanager.v1.ReportServiceClient;

public class SyncFetchReportResultRowsString {

  public static void main(String[] args) throws Exception {
    syncFetchReportResultRowsString();
  }

  public static void syncFetchReportResultRowsString() throws Exception {
    try (ReportServiceClient reportServiceClient = ReportServiceClient.create()) {
      String name = "networks/[NETWORK_CODE]/reports/[REPORT_ID]/results/[RESULT_ID]";
      for (Report.DataTable.Row element :
          reportServiceClient.fetchReportResultRows(name).iterateAll()) {
      }
    }
  }
}

Python

from google.ads import admanager_v1


def sample_fetch_report_result_rows():
    # Create a client
    client = admanager_v1.ReportServiceClient()

    # Initialize request argument(s)
    request = admanager_v1.FetchReportResultRowsRequest(
    )

    # Make the request
    page_result = client.fetch_report_result_rows(request=request)

    # Handle the response
    for response in page_result:
        print(response)

.NET

using Google.Ads.AdManager.V1;
using Google.Api.Gax;
using System;

public sealed partial class GeneratedReportServiceClientSnippets
{
    public void FetchReportResultRows()
    {
        // Create client
        ReportServiceClient reportServiceClient = ReportServiceClient.Create();
        // Initialize request argument(s)
        string name = "";
        // Make the request
        PagedEnumerable<FetchReportResultRowsResponse, Report.Types.DataTable.Types.Row> response = reportServiceClient.FetchReportResultRows(name);

        // Iterate over all response items, lazily performing RPCs as required
        foreach (Report.Types.DataTable.Types.Row item in response)
        {
            // Do something with each item
            Console.WriteLine(item);
        }

        // Or iterate over pages (of server-defined size), performing one RPC per page
        foreach (FetchReportResultRowsResponse page in response.AsRawResponses())
        {
            // Do something with each page of items
            Console.WriteLine("A page of results:");
            foreach (Report.Types.DataTable.Types.Row item in page)
            {
                // Do something with each item
                Console.WriteLine(item);
            }
        }

        // Or retrieve a single page of known size (unless it's the final page), performing as many RPCs as required
        int pageSize = 10;
        Page<Report.Types.DataTable.Types.Row> singlePage = response.ReadPage(pageSize);
        // Do something with the page of items
        Console.WriteLine($"A page of {pageSize} results (unless it's the final page):");
        foreach (Report.Types.DataTable.Types.Row item in singlePage)
        {
            // Do something with each item
            Console.WriteLine(item);
        }
        // Store the pageToken, for when the next page is required.
        string nextPageToken = singlePage.NextPageToken;
    }
}

cURL

初始请求

curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"https://admanager.googleapis.com/v1/networks/${NETWORK_CODE}/reports/${REPORT_ID}/results/${RESULT_ID}:fetchRows"

下一页请求

curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"https://admanager.googleapis.com/v1/networks/${NETWORK_CODE}/reports/${REPORT_ID}/results/${RESULT_ID}:fetchRows?pageToken=${PAGE_TOKEN}"

排查报告问题

为什么 API 中未返回我的报告?
确保您要使用哪个 Ad Manager 用户进行身份验证的用户有权访问“互动”报告。您只能通过 Ad Manager API 读取互动式报告。
为什么我的测试网络上的报告结果为空?
测试广告联盟不会投放广告,因此投放情况报告中没有数据。
为什么我正式版广告网络的报告结果为空?
您尝试以哪位用户的身份进行身份验证的用户可能无权访问您尝试生成报告的数据。验证其角色权限团队设置是否正确。
为什么整个生命周期内的点击次数或展示次数与界面中的报告不一致?
“生命周期内的展示次数”是指订单项的整个生命周期内的展示次数,不受报告日期范围的影响。如果订单项仍在投放,则在两次生成同一报告之间,该值可能会发生变化。