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

เกริ่นนำ

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

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

Primer

หากคุณไม่คุ้นเคยกับการรายงานใน Ad Manager ให้ดูภาพรวมวิธีเรียกใช้รายงานใน UI ของ Ad Manager ที่สร้างรายงานใหม่ UI มีหน้าตัวอย่างของเอาต์พุตและเคล็ดลับเครื่องมือที่อธิบายว่าระบบรองรับชุดค่าผสมของคอลัมน์และมิติข้อมูลใดบ้าง เมื่อสร้าง Query รายงานที่ซับซ้อน คุณอาจสร้าง Query ดังกล่าวใน UI ก่อนแล้วจึงเรียก Query ด้วย 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='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
      }
  }
    

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

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

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 ฉบับใดก็ตาม
รายงานของฉันใช้เวลานานเกินไปและหมดเวลาเป็นครั้งคราว What can I do?
การลดช่วงวันที่หรือจำนวนมิติข้อมูลจะช่วยปรับปรุงประสิทธิภาพ ให้ลองเรียกใช้รายงานหลายรายการสำหรับช่วงวันที่ที่สั้นกว่าเดิมแทน จากนั้นคุณสามารถรวมข้อมูลรายงานเพื่อให้ครอบคลุมช่วงวันที่ที่ต้องการ
INVENTORY_LEVEL และ LINE_ITEM_LEVEL คอลัมน์แตกต่างกันอย่างไร ฉันควรใช้แบบใด

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

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