보고서 기본사항

소개

이 가이드에서는 API를 사용하여 보고서를 실행하고 다운로드하는 방법을 설명합니다. 기존에 저장된 보고서 쿼리를 사용하는 방법과 임시 보고서 쿼리를 만드는 방법을 모두 다룹니다.

기본 요건

Primer

Ad Manager의 보고에 익숙하지 않다면 새 보고서 만들기에서 Ad Manager UI에서 보고서를 실행하는 방법에 관한 개요를 확인하세요. UI에는 출력 미리보기와 지원되는 열 및 측정기준 조합을 설명하는 도움말이 제공됩니다. 복잡한 보고서 쿼리를 만드는 경우 먼저 UI에서 쿼리를 만든 후 API를 사용하여 쿼리를 검색하는 것이 더 쉬울 수 있습니다.

저장된 ReportQuery 검색

ReportQuery 객체에는 보고서의 모든 세부정보가 포함됩니다. Ad Manager UI에서 보고서 쿼리를 만들고 ReportService.getSavedQueriesByStatement 메서드를 사용하여 쿼리를 검색할 수 있습니다. 저장된 쿼리 ID는 UI에서 쿼리를 볼 때 URL에 포함됩니다. 예를 들어 URL https://www.google.com/admanager/1234#reports/report/detail/report_id=456789에서 쿼리 ID는 456789입니다.

쿼리가 API 버전과 호환되지 않는 경우 SavedQuery.reportQuerynull가 되고 SavedQuery.isCompatibleWithApiVersionfalse가 됩니다.

호환되는 저장된 쿼리는 수정 여부와 관계없이 실행할 수 있습니다.

Java


    StatementBuilder statementBuilder =
        new StatementBuilder()
            .where("id = :id")
            .orderBy("id ASC")
            .limit(1)
            .withBindVariableValue("id", savedQueryId);

    SavedQueryPage page = reportService.getSavedQueriesByStatement(statementBuilder.toStatement());
    SavedQuery savedQuery = Iterables.getOnlyElement(Arrays.asList(page.getResults()));

    if (!savedQuery.getIsCompatibleWithApiVersion()) {
      throw new IllegalStateException("The saved query is not compatible with this API version.");
    }

    ReportQuery reportQuery = savedQuery.getReportQuery();
    

Python


  statement = (ad_manager.StatementBuilder(version='v202402')
               .Where('id = :id')
               .WithBindVariable('id', int(saved_query_id))
               .Limit(1))

  response = report_service.getSavedQueriesByStatement(
      statement.ToStatement())

  if 'results' in response and len(response['results']):
    saved_query = response['results'][0]

    if saved_query['isCompatibleWithApiVersion']:
      report_job = {}

      # Set report query and optionally modify it.
      report_job['reportQuery'] = saved_query['reportQuery']
    

PHP


      $statementBuilder = (new StatementBuilder())->where('id = :id')
          ->orderBy('id ASC')
          ->limit(1)
          ->withBindVariableValue('id', $savedQueryId);

      $savedQueryPage = $reportService->getSavedQueriesByStatement(
          $statementBuilder->toStatement()
      );
      $savedQuery = $savedQueryPage->getResults()[0];

      if ($savedQuery->getIsCompatibleWithApiVersion() === false) {
          throw new UnexpectedValueException(
              'The saved query is not compatible with this API version.'
          );
      }

      $reportQuery = $savedQuery->getReportQuery();
    

C#


StatementBuilder statementBuilder = new StatementBuilder()
    .Where("id = :id")
    .OrderBy("id ASC")
    .Limit(1)
    .AddValue("id", savedQueryId);

SavedQueryPage page =
    reportService.getSavedQueriesByStatement(statementBuilder.ToStatement());
SavedQuery savedQuery = page.results[0];

if (!savedQuery.isCompatibleWithApiVersion)
{
    throw new InvalidOperationException("Saved query is not compatible with this " +
        "API version");
}

// Optionally modify the query.
ReportQuery reportQuery = savedQuery.reportQuery;
    

Ruby


  statement = ad_manager.new_statement_builder do |sb|
    sb.where = 'id = :saved_query_id'
    sb.with_bind_variable('saved_query_id', saved_query_id)
  end

  saved_query_page = report_service.get_saved_queries_by_statement(
      statement.to_statement()
  )

  unless saved_query_page[:results].nil?
    saved_query = saved_query_page[:results].first

    if saved_query[:is_compatible_with_api_version]
      # Create report job.
      report_job = {:report_query => saved_query[:report_query]}
    else
      raise StandardError, 'Report query is not compatible with the API'
    end
    

쿼리를 실행하려면 ReportJob 만들기를 참조하세요.

ReportQuery 빌드

저장된 쿼리를 사용하는 것 외에 임시 ReportQuery를 만들 수도 있습니다. 이렇게 하려면 보고서의 측정기준, 측정기준 속성, , 필터, 기간을 설정해야 합니다. 다음은 단일 주문에 대한 기본 전송 보고서 예시입니다.

Java


    // Create report query.
    ReportQuery reportQuery = new ReportQuery();
    reportQuery.setDimensions(new Dimension[] {Dimension.DATE, Dimension.ORDER_ID});
    reportQuery.setColumns(
        new Column[] {
          Column.AD_SERVER_IMPRESSIONS,
          Column.AD_SERVER_CLICKS,
          Column.AD_SERVER_CTR,
          Column.AD_SERVER_CPM_AND_CPC_REVENUE
        });
    reportQuery.setDimensionAttributes(
        new DimensionAttribute[] {
          DimensionAttribute.ORDER_TRAFFICKER,
          DimensionAttribute.ORDER_START_DATE_TIME,
          DimensionAttribute.ORDER_END_DATE_TIME
        });

    // Create statement to filter for an order.
    StatementBuilder statementBuilder =
        new StatementBuilder()
            .where("ORDER_ID = :orderId")
            .withBindVariableValue("orderId", orderId);

    // Set the filter statement.
    reportQuery.setStatement(statementBuilder.toStatement());

    // Set the start and end dates or choose a dynamic date range type.
    reportQuery.setDateRangeType(DateRangeType.CUSTOM_DATE);
    reportQuery.setStartDate(
        DateTimes.toDateTime("2013-05-01T00:00:00", "America/New_York").getDate());
    reportQuery.setEndDate(
        DateTimes.toDateTime("2013-05-31T00:00:00", "America/New_York").getDate());
    

Python


  # Create statement object to filter for an order.
  statement = (ad_manager.StatementBuilder(version='v202402')
               .Where('ORDER_ID = :id')
               .WithBindVariable('id', int(order_id))
               .Limit(None)  # No limit or offset for reports
               .Offset(None))

  # Set the start and end dates of the report to run (past 8 days).
  end_date = datetime.now().date()
  start_date = end_date - timedelta(days=8)

  # Create report job.
  report_job = {
      'reportQuery': {
          'dimensions': ['ORDER_ID', 'ORDER_NAME'],
          'dimensionAttributes': ['ORDER_TRAFFICKER', 'ORDER_START_DATE_TIME',
                                  'ORDER_END_DATE_TIME'],
          'statement': statement.ToStatement(),
          'columns': ['AD_SERVER_IMPRESSIONS', 'AD_SERVER_CLICKS',
                      'AD_SERVER_CTR', 'AD_SERVER_CPM_AND_CPC_REVENUE',
                      'AD_SERVER_WITHOUT_CPD_AVERAGE_ECPM'],
          'dateRangeType': 'CUSTOM_DATE',
          'startDate': start_date,
          'endDate': end_date
      }
  }
    

2,399필리핀


      // Create report query.
      $reportQuery = new ReportQuery();
      $reportQuery->setDimensions(
          [
              Dimension::ORDER_ID,
              Dimension::ORDER_NAME
          ]
      );
      $reportQuery->setDimensionAttributes(
          [
              DimensionAttribute::ORDER_TRAFFICKER,
              DimensionAttribute::ORDER_START_DATE_TIME,
              DimensionAttribute::ORDER_END_DATE_TIME
          ]
      );
      $reportQuery->setColumns(
          [
              Column::AD_SERVER_IMPRESSIONS,
              Column::AD_SERVER_CLICKS,
              Column::AD_SERVER_CTR,
              Column::AD_SERVER_CPM_AND_CPC_REVENUE,
              Column::AD_SERVER_WITHOUT_CPD_AVERAGE_ECPM
          ]
      );

      // Create statement to filter for an order.
      $statementBuilder = (new StatementBuilder())
          ->where('ORDER_ID = :orderId')
          ->withBindVariableValue(
              'orderId',
              $orderId
          );

      // Set the filter statement.
      $reportQuery->setStatement($statementBuilder->toStatement());

      // Set the start and end dates or choose a dynamic date range type.
      $reportQuery->setDateRangeType(DateRangeType::CUSTOM_DATE);
      $reportQuery->setStartDate(
          AdManagerDateTimes::fromDateTime(
              new DateTime(
                  '-10 days',
                  new DateTimeZone('America/New_York')
              )
          )
              ->getDate()
      );
      $reportQuery->setEndDate(
          AdManagerDateTimes::fromDateTime(
              new DateTime(
                  'now',
                  new DateTimeZone('America/New_York')
              )
          )
              ->getDate()
      );
    

C#


// Create report job.
ReportJob reportJob = new ReportJob();
reportJob.reportQuery = new ReportQuery();
reportJob.reportQuery.dimensions = new Dimension[]
{
    Dimension.ORDER_ID,
    Dimension.ORDER_NAME
};
reportJob.reportQuery.dimensionAttributes = new DimensionAttribute[]
{
    DimensionAttribute.ORDER_TRAFFICKER,
    DimensionAttribute.ORDER_START_DATE_TIME,
    DimensionAttribute.ORDER_END_DATE_TIME
};
reportJob.reportQuery.columns = new Column[]
{
    Column.AD_SERVER_IMPRESSIONS,
    Column.AD_SERVER_CLICKS,
    Column.AD_SERVER_CTR,
    Column.AD_SERVER_CPM_AND_CPC_REVENUE,
    Column.AD_SERVER_WITHOUT_CPD_AVERAGE_ECPM
};

// Set a custom date range for the last 8 days
reportJob.reportQuery.dateRangeType = DateRangeType.CUSTOM_DATE;
System.DateTime endDateTime = System.DateTime.Now;
reportJob.reportQuery.startDate = DateTimeUtilities
    .FromDateTime(endDateTime.AddDays(-8), "America/New_York").date;
reportJob.reportQuery.endDate = DateTimeUtilities
    .FromDateTime(endDateTime, "America/New_York").date;

// Create statement object to filter for an order.
StatementBuilder statementBuilder = new StatementBuilder().Where("ORDER_ID = :id")
    .AddValue("id", orderId);
reportJob.reportQuery.statement = statementBuilder.ToStatement();
    

Ruby


  # Specify a report to run for the last 7 days.
  report_end_date = ad_manager.today()
  report_start_date = report_end_date - 7

  # Create statement object to filter for an order.
  statement = ad_manager.new_report_statement_builder do |sb|
    sb.where = 'ORDER_ID = :order_id'
    sb.with_bind_variable('order_id', order_id)
  end

  # Create report query.
  report_query = {
    :date_range_type => 'CUSTOM_DATE',
    :start_date => report_start_date.to_h,
    :end_date => report_end_date.to_h,
    :dimensions => ['ORDER_ID', 'ORDER_NAME'],
    :dimension_attributes => ['ORDER_TRAFFICKER', 'ORDER_START_DATE_TIME',
        'ORDER_END_DATE_TIME'],
    :columns => ['AD_SERVER_IMPRESSIONS', 'AD_SERVER_CLICKS', 'AD_SERVER_CTR',
        'AD_SERVER_CPM_AND_CPC_REVENUE', 'AD_SERVER_WITHOUT_CPD_AVERAGE_ECPM'],
    :statement => statement.to_statement()
  }
    

ReportJob 생성

ReportQuery가 만들어졌으면 보고서를 실행해 보겠습니다. ReportJob 객체는 보고서의 상태를 보유하고, 다운로드할 준비가 되면 이를 사용자에게 알려줍니다. 보고서 실행을 시작하려면 ReportService.runReportJob 메서드를 사용하세요.

Java


    // Create report job.
    ReportJob reportJob = new ReportJob();
    reportJob.setReportQuery(reportQuery);

    // Run report job.
    reportJob = reportService.runReportJob(reportJob);
    

Python


  # Initialize a DataDownloader.
  report_downloader = client.GetDataDownloader(version='v202402')

  try:
    # Run the report and wait for it to finish.
    report_job_id = report_downloader.WaitForReport(report_job)
  except errors.AdManagerReportError as e:
    print('Failed to generate report. Error was: %s' % e)
    

2,399필리핀


      // Create report job and start it.
      $reportJob = new ReportJob();
      $reportJob->setReportQuery($reportQuery);
      $reportJob = $reportService->runReportJob($reportJob);
    

C#


// Run report job.
reportJob = reportService.runReportJob(reportJob);
    

Ruby


  # Create report job.
  report_job = {:report_query => report_query}

  # Run report job.
  report_job = report_service.run_report_job(report_job);
    

보고서 다운로드

보고서 작업을 시작하면 서버에서 설정한 ID를 갖게 됩니다. 이 ID를 ReportService.getReportJobStatus 메서드와 함께 사용하여 보고서 상태를 확인합니다. 상태가 ReportJobStatus.COMPLETED가 되면 보고서를 다운로드할 준비가 된 것입니다.

일부 클라이언트 라이브러리에는 API를 폴링하고 보고서가 완료될 때까지 기다리는 도우미 유틸리티가 있습니다. 보고서가 완료되면 ReportService.getReportDownloadURL 메서드로 다운로드 URL을 가져올 수 있습니다. 보고서는 다양한 형식으로 다운로드할 수 있습니다. 보고서를 머신으로 추가 처리하려면 CSV_DUMP 형식을 사용해야 합니다.

Java


    // Create report downloader.
    ReportDownloader reportDownloader = new ReportDownloader(reportService, reportJob.getId());

    // Wait for the report to be ready.
    if (reportDownloader.waitForReportReady()) {
      // Change to your file location.
      File file = File.createTempFile("delivery-report-", ".csv.gz");

      System.out.printf("Downloading report to %s ...", file.toString());

      // Download the report.
      ReportDownloadOptions options = new ReportDownloadOptions();
      options.setExportFormat(ExportFormat.CSV_DUMP);
      options.setUseGzipCompression(true);
      URL url = reportDownloader.getDownloadUrl(options);
      Resources.asByteSource(url).copyTo(Files.asByteSink(file));

      System.out.println("done.");
    } else {
      System.out.printf("Report job %d failed.%n", reportJob.getId());
    }
    

Python


  # Change to your preferred export format.
  export_format = 'CSV_DUMP'

  report_file = tempfile.NamedTemporaryFile(suffix='.csv.gz', delete=False)

  # Download report data.
  report_downloader.DownloadReportToFile(
      report_job_id, export_format, report_file)

  report_file.close()

  # Display results.
  print('Report job with id "%s" downloaded to:\n%s' % (
      report_job_id, report_file.name))
    

2,399필리핀


      // Create report downloader to poll report's status and download when
      // ready.
      $reportDownloader = new ReportDownloader(
          $reportService,
          $reportJob->getId()
      );
      if ($reportDownloader->waitForReportToFinish()) {
          // Write to system temp directory by default.
          $filePath = sprintf(
              '%s.csv.gz',
              tempnam(sys_get_temp_dir(), 'delivery-report-')
          );
          printf("Downloading report to %s ...%s", $filePath, PHP_EOL);
          // Download the report.
          $reportDownloader->downloadReport(
              ExportFormat::CSV_DUMP,
              $filePath
          );
          print "done.\n";
      } else {
          print "Report failed.\n";
      }
    

C#


ReportUtilities reportUtilities =
    new ReportUtilities(reportService, reportJob.id);

// Set download options.
ReportDownloadOptions options = new ReportDownloadOptions();
options.exportFormat = ExportFormat.CSV_DUMP;
options.useGzipCompression = true;
reportUtilities.reportDownloadOptions = options;

// Download the report.
using (ReportResponse reportResponse = reportUtilities.GetResponse())
{
    reportResponse.Save(filePath);
}

Console.WriteLine("Report saved to \"{0}\".", filePath);
    

Ruby


  MAX_RETRIES.times do |retry_count|
    # Get the report job status.
    report_job_status = report_service.get_report_job_status(report_job[:id])

    break unless report_job_status == 'IN_PROGRESS'
    puts 'Report with ID %d is still running.' % report_job[:id]
    sleep(RETRY_INTERVAL)
  end

  puts 'Report job with ID %d finished with status "%s".' % [report_job[:id],
      report_service.get_report_job_status(report_job[:id])]

  # Get the report URL.
  download_url = report_service.get_report_download_url(
      report_job_id, export_format
  )

  puts 'Downloading "%s" to "%s"...' % [download_url, file_name]
  open(file_name, 'wb') do |local_file|
    local_file << open(download_url).read()
  end
    

보고서 데이터 읽기

대부분의 클라이언트 라이브러리에는 보고서 데이터를 읽기 위한 유틸리티가 포함되어 있습니다. 이는 보고서 데이터를 추가 처리하거나 서로 다른 기간의 보고서를 결합할 때 유용합니다. 코드 예에서는 파일이 압축되지 않았다고 가정합니다.

Java


  List rows = CsvFiles.getCsvDataArray(filePath, true);
  for (String[] row : rows) {
    // Additional row processing
    processReportRow(row);
  }
    

Python


  with open(report_file.name, 'rb') as report:
    report_reader = csv.reader(report)
    for row in report_reader:
      # Additional row processing
      process_row(row)
    

2,399필리핀


  $report = fopen($filePath, 'r');
  while (!feof($report)) {
    // Additional row processing
    processRow(fgetcsv($report));
  }
  fclose($report);
    

C#


  CsvFile file = new CsvFile();
  file.Read(fileName, true);
  for (String[] row : file.Records) {
    // Additional row processing
    ProcessReportRow(row);
  }
    

Ruby


    CSV.foreach(file_name, converters: :numeric, headers: true) do |row|
      # Additional row processing
      process_row(row)
    end
    

더 많은 보고 예를 보려면 GitHub의 클라이언트 라이브러리를 확인하세요.

FAQ

테스트 네트워크의 모든 보고서 결과가 비어 있는 이유는 무엇인가요?
테스트 네트워크에서는 광고를 게재하지 않으므로 게재 보고서에는 데이터가 포함되지 않습니다.
프로덕션 네트워크의 모든 보고서 결과가 비어 있는 이유는 무엇인가요?
인증하는 사용자에게 보고하려는 데이터에 대한 액세스 권한이 없을 수 있습니다. 역할 권한이 올바르게 설정되어 있는지 확인합니다.
보고서에 ReportError.COLUMNS_NOT_SUPPORTED_FOR_REQUESTED_DIMENSIONS 오류가 표시되는 이유는 무엇인가요?
Ad Manager에서는 열과 측정기준의 모든 조합이 지원되지 않습니다. 복잡한 보고서의 경우 UI에서 유효한 보고서를 빌드한 후 ReportService.getSavedQueriesByStatement 메서드를 사용하여 보고서를 검색하는 것이 더 쉬울 수 있습니다.
저장된 보고서가 API에서 반환되지 않는 이유는 무엇인가요?
보고서 소유자가 내가 인증하는 사용자와 보고서를 공유했는지 확인합니다.
저장된 보고서가 API와 호환되지 않는 이유는 무엇인가요?
일부 보고 기능은 API에서 지원되지 않습니다. 여기에는 열, 측정기준 속성, 측정기준, 기간 유형이 포함됩니다. 호환되지 않는 기간 유형의 경우 지원되는 유형으로 보고서를 저장하여 검색할 수 있도록 한 다음 ReportQuery를 원하는 고정 기간에 맞게 변경할 수 있습니다.
전체 기간 클릭수/노출수가 UI의 내 보고서와 일치하지 않는 이유는 무엇인가요?
평생 노출수는 보고서 기간에 관계없이 광고 항목의 전체 기간 동안 집계됩니다. 광고 항목이 아직 게재되고 있는 경우 두 보고서 실행 사이에 값이 변경될 수 있습니다.
보고서가 너무 오래 걸리고 가끔 시간이 초과됩니다. 어떻게 해야 할까요?
기간 또는 측정기준 수를 줄이면 실적을 개선하는 데 도움이 됩니다. 대신 더 짧은 기간에 대해 여러 개의 보고서를 실행해 보세요. 그런 다음 원하는 기간을 포함하도록 보고서 데이터를 병합할 수 있습니다.
INVENTORY_LEVEL 열과 LINE_ITEM_LEVEL 열의 차이점은 무엇인가요? 어떤 것을 사용해야 하나요?

LINE_ITEM_LEVEL가 있는 열은 네트워크에서 광고 항목 수준의 동적 할당을 사용 설정한 경우에만 사용할 수 있습니다. 이 열에는 애드센스 또는 Ad Exchange로의 광고 항목 수준 동적 할당 데이터가 포함됩니다. 마찬가지로 INVENTORY_LEVEL 열에는 인벤토리 수준 동적 할당의 데이터가 포함됩니다. 동적 할당에 대해 자세히 알아보려면 Ad Exchange 광고 항목을 참조하세요.

어떤 API 열을 사용해야 할지 잘 모르겠다면 Ad Manager UI에 저장된 쿼리를 만들고 ReportService.getSavedQueriesByStatement 메서드를 사용하여 쿼리를 가져오세요.