Podstawy raportowania

Wprowadzenie

Z tego przewodnika dowiesz się, jak wygenerować i pobrać raport za pomocą interfejsu API. Obejmuje on używając zapisanego zapytania raportu i tworząc zapytanie doraźne.

Wymagania wstępne

Primer

Jeśli nie znasz jeszcze funkcji raportowania w usłudze Ad Manager, przeczytaj artykuł Utwórz nowy raport do Omówienie sposobu generowania raportu w interfejsie Ad Managera. W interfejsie znajduje się podgląd funkcji dane wyjściowe, a także podpowiedzi wyjaśniające, które kombinacje kolumn i wymiarów są obsługiwane. Przy tworzeniu złożonego zapytania dotyczącego raportu łatwiej jest utworzyć najpierw w interfejsie, a następnie pobierz zapytanie za pomocą interfejsu API.

Pobieranie zapisanego zapytania dotyczącego raportu

Zapytanie ReportQuery zawiera wszystkie szczegóły raportu. Zapytania dotyczące raportów możesz tworzyć w w interfejsie Ad Managera, i pobierać je za pomocą polecenia ReportService.getSavedQueriesByStatement . Identyfikator zapisanego zapytania jest zawarty w adresie URL podczas wyświetlania zapytania w Interfejs. Na przykład w adresie URL https://www.google.com/admanager/1234#reports/report/detail/report_id=456789 identyfikator zapytania to 456789.

Jeśli zapytanie nie jest zgodne z Twoją wersją interfejsu API, SavedQuery.reportQuery będzie null i SavedQuery.isCompatibleWithApiVersion będzie false.

Zgodne zapisane zapytania można uruchamiać z modyfikacją lub bez niej.

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
    

Aby uruchomić zapytanie, patrz Tworzenie zadania ReportJob.

Tworzenie zapytania dotyczącego raportu

Oprócz korzystania z zapisanych zapytań możesz też tworzyć doraźne zapytania ReportQuery. Aby to zrobić, ustaw w raporcie parametr wymiarów, wymiar atrybutów, kolumny, filtruj i zakresu dat. Ten przykład dotyczy podstawowego raportu o wyświetlaniu w przypadku jednego zamówienia.

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

Tworzenie zadania raportowania

Po utworzeniu zapytania ReportQuery możesz wygenerować raport. Obiekt ReportJob zachowuje stan raportu i informuje, kiedy jest on gotowy do pobrania. Do zacznij generować raport, skorzystaj z 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);
    

Pobieranie raportu

Po uruchomieniu zadania raportowania otrzyma ono identyfikator ustawiony przez serwer. Użyj tej Identyfikator z ReportService.getReportJobStatus . Gdy stan zmieni się na ReportJobStatus.COMPLETED raport jest gotowy do pobrania.

Niektóre z naszych bibliotek klienta zawierają narzędzia pomocnicze, które odpytują API i poczekaj na zakończenie raportu. Po wygenerowaniu raportu można wyświetlić adres URL pobierania z parametrem ReportService.getReportDownloadURL . Raport można pobrać w różnych formatach. Jeśli chcesz do przetwarzania maszynowego, użyj 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
    

Odczytywanie danych z raportu

Wiele naszych bibliotek klienckich zawiera narzędzia do odczytywania danych z raportów. To jest przydatne przy dodatkowym przetwarzaniu danych w raportach lub łączeniu raportów różnych zakresów dat. Pamiętaj, że przykładowy kod zakłada, że plik nie jest skompresowane.

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
    

Więcej przykładów raportowania znajdziesz w naszym kliencie w GitHubie.

Najczęstsze pytania

Dlaczego wszystkie wyniki raportu w mojej sieci testowej są puste?
Sieci testowe nie wyświetlają reklam, więc raporty o wyświetlaniu nie będą miały danych.
Dlaczego wszystkie wyniki raportu w mojej sieci produkcyjnej są puste?
Użytkownik, za którego się uwierzytelniasz, może nie mieć dostępu do danych, których dotyczy raport. Sprawdź, czy użytkownik uprawnienia ról oraz zespoły są ustawione prawidłowo.
Dlaczego w moim raporcie pojawia się błąd ReportError.COLUMNS_NOT_SUPPORTED_FOR_REQUESTED_DIMENSIONS?
Ad Manager nie obsługuje wszystkich kombinacji kolumn i wymiarów. W przypadku złożonych raportów łatwiej może być utworzyć prawidłowy raport w interfejsie, a następnie pobrać go za pomocą metody ReportService.getSavedQueriesByStatement.
Dlaczego mój zapisany raport nie jest zwracany do interfejsu API?
Upewnij się, że właściciel zgłoszenia udostępnił je użytkownikowi, pod którego tożsamością się uwierzytelniasz.
Dlaczego zapisany raport nie jest zgodny z interfejsem API?
Niektóre funkcje raportowania są niedostępne w interfejsie API. Obejmuje to m.in. kolumny, atrybuty wymiarów, wymiary i typy zakresów dat. Dla: niezgodnych typów zakresów dat, można zapisać raport z obsługiwanym typem włącz jego pobieranie, a następnie zmień ReportQuery, aby mieścił się w oczekiwanym, stałym zakresie dat.
Dlaczego łączna liczba kliknięć lub wyświetleń różni się od wartości w moim raporcie w interfejsie?
Wyświetlenia łącznie dotyczą całego okresu aktywności elementu zamówienia, niezależnie od zakres dat raportu. Jeśli element zamówienia nadal wyświetla reklamy, wartość będzie prawdopodobnie nie zmieni się pomiędzy generowaniem dwóch raportów.
Wysyłanie raportów trwa zbyt długo, a czasem przekroczono limit czasu. Co mogę zrobić?
Zmniejszenie zakresu dat lub zmniejszenie liczby wymiarów może pomóc w poprawie wyników. skuteczność reklam. Spróbuj wygenerować kilka raportów dla mniejszych zakresów dat. Ty mogą następnie scalić dane z raportu, aby obejmowały odpowiedni zakres dat.
Jaka jest różnica między kolumnami INVENTORY_LEVEL i LINE_ITEM_LEVEL? Którego z nich mam użyć?

Kolumn zawierających LINE_ITEM_LEVEL można używać tylko na poziomie elementu zamówienia alokacja dynamiczna w Twojej sieci. Kolumny te zawierają dane z alokacja dynamiczna na poziomie elementu zamówienia do AdSense lub Ad Exchange. Podobnie INVENTORY_LEVEL kolumny zawierają dane z alokacji dynamicznej na poziomie zasobów reklamowych. Więcej informacji o alokacji dynamicznej znajdziesz w artykule Elementy zamówienia Ad Exchange.

Jeśli nadal nie masz pewności, których kolumn interfejsu API użyć, utwórz zapisane zapytanie w interfejsu Ad Managera i pobieraj go za pomocą ReportService.getSavedQueriesByStatement .