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

บทนำ

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

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

Primer

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

การสร้าง Report Query

นอกจากการใช้ Query ที่บันทึกไว้แล้ว คุณยังสร้าง 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='v202408')
               .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='v202408')

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