مبانی گزارش

معرفی

این راهنما به شما نشان می دهد که چگونه یک گزارش را با API اجرا و دانلود کنید. هم استفاده از پرس و جوی گزارش ذخیره شده موجود و هم ایجاد یک درخواست گزارش موقت را پوشش می دهد.

پیش نیازها

آغازگر

اگر با گزارش‌دهی در Ad Manager آشنا نیستید، برای مروری بر نحوه اجرای گزارش در رابط کاربری Ad Manager به ایجاد گزارش جدید مراجعه کنید. رابط کاربری دارای پیش نمایشی از خروجی و همچنین نکاتی است که توضیح می دهد کدام ستون و ترکیب ابعاد پشتیبانی می شود. هنگام ایجاد یک پرس و جو گزارش پیچیده، ممکن است ساده تر باشد که ابتدا آن را در UI ایجاد کنید، و سپس پرس و جو را با API بازیابی کنید.

بازیابی یک ReportQuery ذخیره شده

شی ReportQuery شامل تمام جزئیات گزارش است. می‌توانید درخواست‌های گزارش را در رابط کاربری Ad Manager ایجاد کنید و آنها را با روش ReportService.getSavedQueriesByStatement بازیابی کنید. شناسه پرس و جو ذخیره شده هنگام مشاهده درخواست در UI در URL گنجانده می شود. برای مثال، در نشانی اینترنتی https://www.google.com/admanager/1234#reports/report/detail/report_id=456789 شناسه درخواست 456789 است.

اگر درخواستی با نسخه API شما سازگار نباشد، SavedQuery.reportQuery null و SavedQuery.isCompatibleWithApiVersion false خواهد بود.

پرس و جوهای ذخیره شده سازگار را می توان با یا بدون تغییر اجرا کرد.

جاوا


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

پایتون


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

سی شارپ


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;
    

روبی


  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 موقت نیز ایجاد کنید. برای انجام این کار، باید ابعاد گزارش، ویژگی‌های ابعاد ، ستون‌ها ، فیلتر و محدوده تاریخ را تنظیم کنید. این مثال برای گزارش تحویل اولیه در یک سفارش است.

جاوا


    // 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());
    

پایتون


  # 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()
      );
    

سی شارپ


// 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();
    

روبی


  # 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 استفاده کنید.

جاوا


    // Create report job.
    ReportJob reportJob = new ReportJob();
    reportJob.setReportQuery(reportQuery);

    // Run report job.
    reportJob = reportService.runReportJob(reportJob);
    

پایتون


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

سی شارپ


// Run report job.
reportJob = reportService.runReportJob(reportJob);
    

روبی


  # 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 استفاده کنید.

جاوا


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

پایتون


  # 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";
      }
    

سی شارپ


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

روبی


  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
    

خواندن داده های گزارش

بسیاری از کتابخانه های مشتری ما دارای ابزارهایی برای خواندن داده های گزارش هستند. این برای انجام پردازش های اضافی روی داده های گزارش یا ترکیب گزارش ها از محدوده های مختلف تاریخ مفید است. توجه داشته باشید که کد مثال فرض می کند که فایل فشرده نشده است.

جاوا


  List rows = CsvFiles.getCsvDataArray(filePath, true);
  for (String[] row : rows) {
    // Additional row processing
    processReportRow(row);
  }
    

پایتون


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

سی شارپ


  CsvFile file = new CsvFile();
  file.Read(fileName, true);
  for (String[] row : file.Records) {
    // Additional row processing
    ProcessReportRow(row);
  }
    

روبی


    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 پشتیبانی نمی‌شوند. برای گزارش‌های پیچیده، ساختن یک گزارش معتبر در رابط کاربری و سپس بازیابی آن با روش ReportService.getSavedQueriesByStatement ممکن است آسان‌تر باشد.
چرا گزارش ذخیره شده من در API برگردانده نمی شود؟
مطمئن شوید که مالک گزارش گزارش را با کاربری که به عنوان احراز هویت شما احراز هویت می کنید به اشتراک گذاشته است.
چرا گزارش ذخیره شده من با API سازگار نیست؟
برخی از ویژگی‌های گزارش‌دهی در API در دسترس نیستند. این شامل ستون‌ها، ویژگی‌های ابعاد، ابعاد و انواع محدوده تاریخ است. برای انواع محدوده تاریخ ناسازگار، می توانید گزارش را با یک نوع پشتیبانی شده ذخیره کنید تا قابل بازیابی باشد، سپس ReportQuery تغییر دهید تا محدوده تاریخ ثابت مورد نظر شما را برآورده کند.
چرا کلیک ها/برداشت های مادام العمر با گزارش من در رابط کاربری مطابقت ندارند؟
نمایش‌های مادام‌العمر برای کل عمر مورد خط، صرف‌نظر از محدوده تاریخ گزارش، هستند. اگر یک مورد خطی همچنان در حال تحویل است، مقدار آن احتمالاً بین اجرای هر دو گزارش تغییر خواهد کرد.
گزارش‌های من بیش از حد طولانی می‌شوند و گهگاهی زمان می‌برند. چه می توانم بکنم؟
کاهش محدوده تاریخ یا تعداد ابعاد به بهبود عملکرد کمک می کند. به جای آن، چندین گزارش را برای بازه های تاریخ کوچکتر اجرا کنید. سپس می توانید داده های گزارش را ادغام کنید تا محدوده تاریخ مورد نظر را پوشش دهید.
تفاوت بین ستون های INVENTORY_LEVEL و LINE_ITEM_LEVEL چیست؟ از کدوم استفاده کنم؟

ستون‌های دارای LINE_ITEM_LEVEL تنها در صورتی می‌توانند استفاده شوند که تخصیص پویا سطح آیتم خط را در شبکه خود فعال کرده باشید. این ستون‌ها شامل داده‌هایی از تخصیص پویا سطح آیتم خط به AdSense یا Ad Exchange است. به طور مشابه، ستون های INVENTORY_LEVEL شامل داده هایی از تخصیص پویا در سطح موجودی است. برای اطلاعات بیشتر درباره تخصیص پویا، به موارد خط Ad Exchange مراجعه کنید.

اگر هنوز مطمئن نیستید از کدام ستون های API استفاده کنید، یک پرس و جو ذخیره شده در رابط کاربری Ad Manager ایجاد کنید و آن را با روش ReportService.getSavedQueriesByStatement بازیابی کنید.