Dasar-Dasar Pelaporan

Pengantar

Panduan ini akan menunjukkan cara menjalankan dan mendownload laporan dengan API. Panduan ini membahas penggunaan kueri laporan tersimpan yang ada dan pembuatan kueri laporan ad hoc.

Prasyarat

  • Akses ke jaringan Google Ad Manager Produksi
  • Library klien Ad Manager

Primer

Jika Anda belum memahami pelaporan di Ad Manager, lihat Membuat laporan baru untuk mengetahui ringkasan cara menjalankan laporan di UI Ad Manager. UI memiliki pratinjau output, serta tooltip yang menjelaskan kombinasi kolom dan dimensi yang didukung. Saat membuat kueri laporan yang kompleks, mungkin akan lebih mudah untuk membuatnya di UI terlebih dahulu, lalu mengambil kueri dengan API.

Mengambil ReportQuery yang disimpan

Objek ReportQuery berisi semua detail laporan. Anda dapat membuat kueri laporan di UI Ad Manager, dan mengambilnya dengan metode ReportService.getSavedQueriesByStatement. ID kueri tersimpan disertakan dalam URL saat melihat kueri di UI. Misalnya, dalam URL https://www.google.com/admanager/1234#reports/report/detail/report_id=456789 ID kuerinya adalah 456789.

Jika kueri tidak kompatibel dengan versi API Anda, SavedQuery.reportQuery akan menjadi null dan SavedQuery.isCompatibleWithApiVersion akan menjadi false.

Kueri tersimpan yang kompatibel dapat dijalankan dengan atau tanpa modifikasi.

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
    

Untuk menjalankan kueri, lihat Membuat ReportJob.

Membuat ReportQuery

Selain menggunakan kueri tersimpan, Anda juga dapat membuat ReportQuery ad hoc. Untuk melakukannya, Anda harus menetapkan dimensi, atribut dimensi, kolom, filter, dan rentang tanggal laporan. Contoh ini adalah untuk laporan pengiriman dasar pada satu pesanan.

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

Membuat ReportJob

Setelah Anda memiliki ReportQuery, saatnya menjalankan laporan. Objek ReportJob menyimpan status laporan, dan memberi tahu Anda saat laporan siap didownload. Untuk mulai menjalankan laporan, gunakan metode 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);
    

Mendownload Laporan

Setelah Anda memulai tugas laporan, tugas tersebut akan memiliki ID yang ditetapkan oleh server. Gunakan ID ini dengan metode ReportService.getReportJobStatus untuk memeriksa status laporan Anda. Setelah statusnya ReportJobStatus.COMPLETED, laporan siap didownload.

Beberapa library klien kami memiliki utilitas bantuan yang akan melakukan polling API dan menunggu laporan selesai. Setelah laporan selesai, Anda bisa mendapatkan URL download dengan metode ReportService.getReportDownloadURL. Laporan dapat didownload dalam berbagai format. Jika Anda ingin melakukan pemrosesan mesin lebih lanjut dengan laporan, Anda harus menggunakan format 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
    

Membaca Data Laporan

Banyak library klien kami menyertakan utilitas untuk membaca data pelaporan. Hal ini berguna untuk melakukan pemrosesan tambahan pada data laporan, atau menggabungkan laporan dari rentang tanggal yang berbeda. Perhatikan bahwa kode contoh mengasumsikan file tidak dikompresi.

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
    

Untuk contoh pelaporan lainnya, lihat library klien kami di GitHub.

FAQ

Mengapa semua hasil laporan di jaringan pengujian saya kosong?
Jaringan pengujian tidak menayangkan iklan, sehingga laporan penayangan tidak akan memiliki data.
Mengapa semua hasil laporan di jaringan produksi saya kosong?
Pengguna yang Anda autentikasi mungkin tidak memiliki akses ke data yang Anda coba laporkan. Pastikan izin peran dan tim mereka ditetapkan dengan benar.
Mengapa saya mendapatkan error ReportError.COLUMNS_NOT_SUPPORTED_FOR_REQUESTED_DIMENSIONS untuk laporan saya?
Tidak semua kombinasi kolom dan dimensi didukung di Ad Manager. Untuk laporan yang kompleks, mungkin akan lebih mudah untuk membuat laporan yang valid di UI, lalu mengambilnya dengan metode ReportService.getSavedQueriesByStatement.
Mengapa laporan tersimpan saya tidak ditampilkan di API?
Pastikan pemilik laporan telah membagikan laporan kepada pengguna yang Anda gunakan untuk melakukan autentikasi.
Mengapa laporan tersimpan saya tidak kompatibel dengan API?
Fitur pelaporan tertentu tidak tersedia di API. Hal ini mencakup kolom, atribut dimensi, dimensi, dan jenis rentang tanggal. Untuk jenis rentang tanggal yang tidak kompatibel, Anda dapat menyimpan laporan dengan jenis yang didukung agar dapat diambil, lalu mengubah ReportQuery untuk memenuhi rentang tanggal tetap yang Anda inginkan.
Mengapa klik/tayangan iklan sepanjang waktu tidak cocok dengan laporan saya di UI?
Tayangan iklan sepanjang waktu adalah untuk seluruh masa aktif item baris, terlepas dari rentang tanggal laporan. Jika item baris masih ditayangkan, nilainya mungkin akan berubah di antara dua laporan yang dijalankan.
Laporan saya memerlukan waktu terlalu lama dan terkadang waktu habis. Apa yang dapat saya lakukan?
Mengurangi rentang tanggal atau jumlah dimensi akan membantu meningkatkan performa. Coba jalankan beberapa laporan untuk rentang tanggal yang lebih kecil. Kemudian, Anda dapat menggabungkan data laporan untuk mencakup rentang tanggal yang diinginkan.
Apa perbedaan antara kolom INVENTORY_LEVEL dan LINE_ITEM_LEVEL? Mana yang harus saya gunakan?

Kolom dengan LINE_ITEM_LEVEL hanya dapat digunakan jika Anda telah mengaktifkan alokasi dinamis tingkat item baris di jaringan. Kolom ini menyertakan data dari alokasi dinamis tingkat item baris ke AdSense atau Ad Exchange. Demikian pula, kolom INVENTORY_LEVEL menyertakan data dari alokasi dinamis tingkat inventaris. Untuk mengetahui informasi selengkapnya tentang alokasi dinamis, lihat Item baris Ad Exchange.

Jika Anda masih tidak yakin kolom API mana yang akan digunakan, buat kueri tersimpan di UI Ad Manager dan ambil dengan metode ReportService.getSavedQueriesByStatement.