Principes de base sur la création de rapports

Introduction

Ce guide vous explique comment générer et télécharger un rapport avec l'API. Il couvre à la fois l'utilisation d'une requête de rapport enregistré existante et la création d'une requête de rapport ad hoc.

Conditions préalables

Primer

Si vous ne savez pas comment créer des rapports dans Ad Manager, consultez l'article Créer un rapport pour découvrir comment générer un rapport dans l'interface utilisateur d'Ad Manager. L'interface utilisateur affiche un aperçu du résultat, ainsi que des info-bulles expliquant les combinaisons de colonne et de dimension acceptées. Lors de la création d'une requête de rapport complexe, il peut être plus facile de la créer d'abord dans l'interface utilisateur, puis de la récupérer avec l'API.

Récupérer une requête ReportQuery enregistrée

L'objet ReportQuery contient tous les détails du rapport. Vous pouvez créer des requêtes de rapport dans l'interface utilisateur d'Ad Manager et les récupérer avec la méthode ReportService.getSavedQueriesByStatement. L'ID de requête enregistrée est inclus dans l'URL lorsque vous consultez une requête dans l'UI. Par exemple, dans l'URL https://www.google.com/admanager/1234#reports/report/detail/report_id=456789, l'ID de requête est 456789.

Si une requête n'est pas compatible avec la version de votre API, SavedQuery.reportQuery sera null et SavedQuery.isCompatibleWithApiVersion sera false.

Les requêtes enregistrées compatibles peuvent être exécutées avec ou sans modification.

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
    

Pour exécuter la requête, consultez la section Créer le ReportJob.

Création d'une requête de rapport

En plus d'utiliser les requêtes enregistrées, vous pouvez également créer une requête ReportQuery ad hoc. Pour ce faire, vous devez définir les dimensions, les attributs, les colonnes, le filtre et la plage de dates du rapport. Cet exemple concerne un rapport de diffusion de base portant sur une seule commande.

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

Créer le ReportJob

Une fois que vous disposez d'un rapport Requête de rapport, vous pouvez générer le rapport. L'objet ReportJob contient l'état d'un rapport et vous indique quand il est prêt à être téléchargé. Pour commencer à exécuter le rapport, utilisez la méthode 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);
    

Télécharger le rapport

Une fois la tâche de rapport démarrée, un ID est défini par le serveur. Utilisez cet ID avec la méthode ReportService.getReportJobStatus pour vérifier l'état de votre rapport. Une fois que l'état indique ReportJobStatus.COMPLETED, le rapport est prêt à être téléchargé.

Certaines de nos bibliothèques clientes disposent d'utilitaires d'assistance qui interrogent l'API et attendent que le rapport soit terminé. Une fois le rapport créé, vous pouvez obtenir l'URL de téléchargement à l'aide de la méthode ReportService.getReportDownloadURL. Un rapport peut être téléchargé dans différents formats. Si vous souhaitez poursuivre le traitement du rapport avec votre machine, utilisez le 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 << open(download_url).read()
  end
    

Lecture des données de rapport

Bon nombre de nos bibliothèques clientes contiennent des utilitaires permettant de lire les données des rapports. Cela est utile pour effectuer un traitement supplémentaire sur les données du rapport ou pour combiner des rapports provenant de différentes plages de dates. Notez que l'exemple de code suppose que le fichier n'est pas compressé.

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
    

Pour plus d'exemples de rapports, consultez nos bibliothèques clientes sur GitHub.

Questions fréquentes

Pourquoi tous les résultats des rapports sur mon réseau de test sont-ils vides ?
Les réseaux de test ne diffusent pas d'annonces. Par conséquent, les rapports de diffusion ne contiendront pas de données.
Pourquoi tous les résultats des rapports sur mon réseau de production sont-ils vides ?
L'utilisateur que vous vous authentifiez n'a peut-être pas accès aux données pour lesquelles vous tentez de créer un rapport. Vérifiez que leurs autorisations de rôle et leurs équipes sont correctement définies.
Pourquoi l'erreur ReportError.COLUMNS_NOT_SUPPORTED_FOR_REQUESTED_DIMENSIONS s'affiche-t-elle pour mon rapport ?
Toutes les combinaisons de colonnes et de dimensions ne sont pas acceptées dans Ad Manager. Pour les rapports complexes, il peut être plus facile de créer un rapport valide dans l'interface utilisateur, puis de le récupérer avec la méthode ReportService.getSavedQueriesByStatement.
Pourquoi mon rapport enregistré n'est-il pas renvoyé dans l'API ?
Assurez-vous que le propriétaire du rapport a partagé le rapport avec l'utilisateur sous lequel vous vous authentifiez.
Pourquoi mon rapport enregistré n'est-il pas compatible avec l'API ?
Certaines fonctionnalités de reporting ne sont pas disponibles dans l'API. Cela inclut les colonnes, les attributs de dimension, les dimensions et les types de plages de dates. Pour les types de plages de dates incompatibles, vous pouvez enregistrer le rapport dans un type compatible afin qu'il puisse être récupéré, puis modifier la ReportQuery pour qu'elle corresponde à la plage de dates fixe souhaitée.
Pourquoi les clics/impressions cumulés ne correspondent-ils pas à ceux indiqués dans le rapport dans l'interface utilisateur ?
Les impressions permanentes concernent toute la durée de vie de l'élément de campagne, quelle que soit la plage de dates couverte par le rapport. Si un élément de campagne est toujours diffusé, la valeur changera probablement entre deux rapports générés.
Mes rapports prennent trop de temps et expirent parfois. What can I do?
Diminuer la plage de dates ou le nombre de dimensions permet d'améliorer les performances. Essayez plutôt de générer plusieurs rapports pour des périodes plus courtes. Vous pouvez ensuite fusionner les données du rapport pour couvrir la plage de dates souhaitée.
Quelle est la différence entre les colonnes INVENTORY_LEVEL et LINE_ITEM_LEVEL ? Lequel dois-je utiliser ?

Les colonnes avec LINE_ITEM_LEVEL ne peuvent être utilisées que si l'allocation dynamique au niveau de l'élément de campagne est activée sur votre réseau. Ces colonnes incluent les données issues de l'allocation dynamique AdSense ou Ad Exchange au niveau de l'élément de campagne. De même, les colonnes INVENTORY_LEVEL incluent les données de l'allocation dynamique au niveau de l'inventaire. Pour en savoir plus sur l'allocation dynamique, consultez la page Éléments de campagne Ad Exchange.

Si vous n'êtes toujours pas sûr des colonnes d'API à utiliser, créez une requête enregistrée dans l'interface utilisateur d'Ad Manager et récupérez-la à l'aide de la méthode ReportService.getSavedQueriesByStatement.