การรายงานพื้นฐาน

บทนำ

คู่มือนี้จะแสดงวิธีเรียกใช้และดาวน์โหลดรายงานด้วย API ซึ่งครอบคลุมทั้ง การใช้คําค้นหารายงานที่บันทึกไว้ที่มีอยู่ และการสร้างคําค้นหารายงานเฉพาะกิจ

ข้อกำหนดเบื้องต้น

Primer

หากคุณไม่คุ้นเคยกับการรายงานใน Ad Manager โปรดดู สร้างรายงานใหม่เพื่อดู ภาพรวมของวิธีเรียกใช้รายงานใน UI ของ Ad Manager UI มีตัวอย่างเอาต์พุต รวมถึงคำแนะนำเครื่องมือที่อธิบายว่าระบบรองรับชุดค่าผสมคอลัมน์และมิติข้อมูลใดบ้าง เมื่อสร้างการค้นหารายงานที่ซับซ้อน การสร้างใน UI ก่อน แล้วจึงดึงข้อมูลการค้นหาด้วย API อาจง่ายกว่า

การดึงข้อมูล ReportQuery ที่บันทึกไว้

ออบเจ็กต์ ReportQuery มีรายละเอียดทั้งหมดของรายงาน คุณสร้างการค้นหารายงานได้ใน UI ของ Ad Manager และเรียกข้อมูลได้ด้วยเมธอด ReportService.getSavedQueriesByStatement รหัสการค้นหาที่บันทึกไว้จะรวมอยู่ใน URL เมื่อดูการค้นหาใน UI เช่น ใน URL https://www.google.com/admanager/1234#reports/report/detail/report_id=456789 รหัสการค้นหาคือ 456789

หากการค้นหาไม่รองรับ API เวอร์ชันของคุณ SavedQuery.reportQuery จะเป็น null และ SavedQuery.isCompatibleWithApiVersion จะเป็น false

คุณเรียกใช้คำค้นหาที่บันทึกไว้ซึ่งเข้ากันได้โดยมีการแก้ไขหรือไม่ก็ได้

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='v202608')
               .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='v202608')
               .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
      }
  }
    

PHP

      // 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='v202608')

  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)
    

PHP

      // 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);
    

การดาวน์โหลดรายงาน

หลังจากเริ่มงานรายงานแล้ว เซิร์ฟเวอร์จะกำหนดรหัสให้ ใช้รหัสนี้ กับเมธอด ReportService.getReportJobStatus เพื่อตรวจสอบสถานะของรายงาน เมื่อสถานะเป็น ReportJobStatus.COMPLETED รายงานจะพร้อมให้ดาวน์โหลด

ไลบรารีของไคลเอ็นต์บางรายการมีเครื่องมือช่วยที่จะสำรวจ API และ รอให้รายงานเสร็จสมบูรณ์ เมื่อรายงานเสร็จสมบูรณ์แล้ว คุณจะรับ URL ดาวน์โหลดได้ด้วยเมธอด ReportService.getReportDownloadURL คุณสามารถดาวน์โหลดรายงานได้ในรูปแบบต่างๆ หากต้องการประมวลผลรายงานด้วยเครื่องต่อไป คุณควรใช้รูปแบบ 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))
    

PHP

      // 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 << URI.open(download_url).read()
  end
    

การอ่านข้อมูลรายงาน

ไลบรารีของไคลเอ็นต์หลายรายการมีเครื่องมือสำหรับอ่านข้อมูลรายงาน ซึ่งมีประโยชน์ในการประมวลผลเพิ่มเติมในข้อมูลรายงาน หรือรวมรายงานจากช่วงวันที่ต่างๆ โปรดทราบว่าโค้ดตัวอย่างถือว่าไฟล์ไม่ได้ บีบอัด

Java

  List<String[]> 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)
    

PHP

  $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

คำถามที่พบบ่อย

เหตุใดผลลัพธ์ของรายงานทั้งหมดในเครือข่ายทดสอบของฉันจึงว่างเปล่า
เครือข่ายทดสอบจะไม่แสดงโฆษณา ดังนั้นรายงานการนำส่งจะไม่มีข้อมูล
เหตุใดผลลัพธ์ของรายงานทั้งหมดในเครือข่ายที่ใช้งานจริงจึงว่างเปล่า
ผู้ใช้ที่คุณกำลังตรวจสอบสิทธิ์อาจไม่มีสิทธิ์เข้าถึงข้อมูลที่คุณพยายามรายงาน ตรวจสอบว่าสิทธิ์ของบทบาทและทีมได้รับการตั้งค่าอย่างถูกต้อง
เหตุใดฉันจึงได้รับข้อผิดพลาด ReportError.COLUMNS_NOT_SUPPORTED_FOR_REQUESTED_DIMENSIONS สำหรับรายงาน
Ad Manager ไม่รองรับชุดค่าผสมคอลัมน์และมิติข้อมูลบางชุด สำหรับรายงานที่ซับซ้อน การสร้างรายงานที่ถูกต้องใน UI แล้ว เรียกข้อมูลด้วยเมธอด ReportService.getSavedQueriesByStatement อาจง่ายกว่า
เหตุใดระบบจึงไม่แสดงรายงานที่บันทึกไว้ใน API
ตรวจสอบว่าเจ้าของรายงานได้แชร์รายงานกับผู้ใช้ที่คุณกำลัง ตรวจสอบสิทธิ์
เหตุใดรายงานที่บันทึกไว้จึงใช้ร่วมกับ API ไม่ได้
ฟีเจอร์การรายงานบางอย่างไม่พร้อมใช้งานใน API ซึ่งรวมถึง คอลัมน์ แอตทริบิวต์ของมิติข้อมูล มิติข้อมูล และประเภทช่วงวันที่ สำหรับประเภทช่วงวันที่ที่ไม่รองรับ คุณสามารถบันทึกรายงานด้วยประเภทที่รองรับเพื่อให้เรียกข้อมูลได้ จากนั้นเปลี่ยนReportQueryเพื่อให้ตรงกับช่วงวันที่แบบคงที่ที่ต้องการ
เหตุใดการคลิก/การแสดงผลตลอดอายุการใช้งานจึงไม่ตรงกับรายงานใน UI
การแสดงผลตลอดอายุการใช้งานมีไว้สำหรับอายุการใช้งานทั้งหมดของรายการโฆษณา ไม่ว่า ช่วงวันที่ของรายงานจะเป็นอย่างไร หากรายการโฆษณายังคงแสดงอยู่ ค่าดังกล่าวอาจเปลี่ยนแปลงระหว่างการเรียกใช้รายงาน 2 ฉบับ
รายงานของฉันใช้เวลานานเกินไปและบางครั้งก็หมดเวลา ฉันต้องทำอย่างไร
การลดช่วงวันที่หรือจำนวนมิติข้อมูลจะช่วยปรับปรุง ประสิทธิภาพ ลองเรียกใช้รายงานหลายรายการสำหรับช่วงวันที่ที่สั้นลงแทน จากนั้นคุณจะผสานข้อมูลรายงานเพื่อให้ครอบคลุมช่วงวันที่ที่ต้องการได้
คอลัมน์ INVENTORY_LEVEL และ LINE_ITEM_LEVEL แตกต่างกันอย่างไร ฉันควรใช้ตัวเลือกใด

คอลัมน์ที่มี LINE_ITEM_LEVEL จะใช้ได้ก็ต่อเมื่อคุณเปิดใช้การจัดสรรแบบไดนามิกระดับรายการโฆษณา ในเครือข่าย คอลัมน์เหล่านี้มีข้อมูลจากการจัดสรรแบบไดนามิกระดับรายการโฆษณาไปยัง AdSense หรือ Ad Exchange ในทำนองเดียวกัน คอลัมน์ INVENTORY_LEVELจะมีข้อมูลจากการจัดสรรแบบไดนามิกระดับพื้นที่โฆษณา ดูข้อมูลเพิ่มเติมเกี่ยวกับการจัดสรรแบบไดนามิกได้ที่รายการโฆษณา Ad Exchange

หากยังไม่แน่ใจว่าจะใช้คอลัมน์ API ใด ให้สร้างการค้นหาที่บันทึกไว้ใน UI ของ Ad Manager แล้วเรียกข้อมูลด้วยเมธอด ReportService.getSavedQueriesByStatement