Create and Access Scheduled Reports

You can create and schedule reports using the Google Display & Video 360 user interface or the API. For example, end users can set up a daily report showing yesterday's impressions, or a monthly report showing total spend.

Create Scheduled Reports

Create a new scheduled report in the Display & Video 360 UI reporting interface or via the Queries.createquery API method. Full details on Display & Video 360's reporting functionality and how to create new reports can be found in the Display & Video 360 support site. The most important field for the purposes of Scheduled Reports is the "Repeats" field, which should be set to an appropriate time interval.

After the "Repeats" field has been set, this report will run at that schedule and the generated reports will then be available for download.

Access Scheduled Reports

Scheduled reports are generated as simple CSV files and are stored automatically and securely in Google Cloud Storage. It isn't possible, however, to access the Google Cloud Storage buckets which contain these files directly. Instead, the files may be manually downloaded from the Display & Video 360 UI or retrieved programmatically using pre-authorized URLs obtained from the API.

An example of using the API to download a report file is provided below. In this example, the Queries.metadata.googleCloudStoragePathForLatestReport convenience field is used to quickly locate the most recent report file for a specified query and download it's contents to a local CSV file.

Java

/*
 * Copyright (c) 2015 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.bidmanager.api.samples;

import com.google.api.client.googleapis.media.MediaHttpDownloader;
import com.google.api.client.googleapis.util.Utils;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpTransport;
import com.google.api.services.doubleclickbidmanager.DoubleClickBidManager;
import com.google.api.services.doubleclickbidmanager.model.ListQueriesResponse;
import com.google.api.services.doubleclickbidmanager.model.Query;
import com.google.common.base.Strings;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;

/**
 * DBM users typically create scheduled reports, where the advertiser uses either the UI or API to
 * create a query that will be used to generate reports based on a daily, weekly, or monthly
 * schedule.
 *
 * In this example for a daily query we check to see if a report has run in the last 12 hours and,
 * if it has, download the data to a local CSV file.
 *
 */
public class GetLatestReport {
  // Twelve hours in milliseconds.
  // In this example, reports created after this date are considered fresh.
  private static final long CURRENT_REPORT_WINDOW_MS = 12 * 60 * 60 * 1000;

  private static final HttpTransport HTTP_TRANSPORT = Utils.getDefaultTransport();

  public static void main(String[] args) throws Exception {
    // Get an authenticated connection to the API.
    DoubleClickBidManager service = DoubleClickBidManagerFactory.getInstance();

    long queryId = getQueryId();
    if (queryId == 0) {
      // Call the API, getting a list of queries.
      ListQueriesResponse queryListResponse = service.queries().listqueries().execute();
      // Print them out.
      System.out.println("Id\t\tName");
      // Starting with the first page.
      printQueries(queryListResponse);
      // Then all other pages.
      while (queryListResponse.getNextPageToken() != null
          && !queryListResponse.getNextPageToken().isEmpty()) {
        queryListResponse =
            service
                .queries()
                .listqueries()
                .setPageToken(queryListResponse.getNextPageToken())
                .execute();
        printQueries(queryListResponse);
      }
    } else {
      // Call the API, getting the latest status for the passed queryId.
      Query query = service.queries().getquery(queryId).execute();

      // If it is recent enough...
      if (query.getMetadata().getLatestReportRunTimeMs()
          > java.lang.System.currentTimeMillis() - CURRENT_REPORT_WINDOW_MS) {
        // Retrieve the download URL for the latest report.
        GenericUrl reportUrl =
            new GenericUrl(query.getMetadata().getGoogleCloudStoragePathForLatestReport());

        // Download the report file.
        try (OutputStream output = new FileOutputStream(query.getQueryId() + ".csv")) {
          MediaHttpDownloader downloader = new MediaHttpDownloader(HTTP_TRANSPORT, null);
          downloader.download(reportUrl, output);
        }

        System.out.println("Download complete.");
      } else {
        System.out.format("No reports for query Id %s in the last 12 hours.", queryId);
      }
    }
  }

  private static void printQueries(ListQueriesResponse queryListResponse) {
    for (Query query : queryListResponse.getQueries()) {
      System.out.format("%s\t%s%n", query.getQueryId(), query.getMetadata().getTitle());
    }
  }

  private static long getQueryId() throws IOException {
    System.out.printf("Enter the query ID or press enter to list queries.%n");

    String input = readInputLine();
    if (!Strings.isNullOrEmpty(input)) {
      return Long.parseLong(input);
    }

    return 0L;
  }

  private static String readInputLine() throws IOException {
    try (BufferedReader in = new BufferedReader(new InputStreamReader(System.in))) {
      return in.readLine();
    }
  }
}

PHP

<?php
/*
 * Copyright 2015 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Require the base class.
require_once __DIR__ . "/../BaseExample.php";

/**
 * DBM users typically create scheduled reports, where the advertiser uses
 * either the UI or API to create a query that will be used to generate reports
 * based on a daily, weekly, or monthly schedule.
 *
 * In this example for a daily query we check to see if a report has run in
 * the last 12 hours and, if it has, download the data to a local csv file.
 */
class GetLatestReport extends BaseExample {
  // Twelve hours in milliseconds: in this example, reports created after this
  // date are considered fresh.  Note: 1000 * 60 * 60 * 12 = 43200000
  const CURRENT_REPORT_WINDOW_MS = 43200000;

  protected function getInputParameters() {
    return array(array(
      'name' => 'query_id',
      'display' => 'Query id',
      'required' => false
    ));
  }

  protected function printQueries($queries) {
    foreach ($queries as $query) {
      printf('<p>%s %s</p>', $query->queryId, $query->metadata->title);
    }
  }

  /**
   * (non-PHPdoc)
   * @see BaseExample::run()
   */
  public function run() {
    $values = $this->formValues;

    $queryId = $values['query_id'];

    if ($queryId === '' || $queryId === 0) {
      // Call the API, getting a list of queries.
      $result = $this->service->queries->listqueries();
      if (isset($result['queries']) && count($result['queries']) > 0) {
        print '<pre>';
        $this->printQueries($result['queries']);
        while (!is_null($result->nextPageToken)
            && !empty($result->nextPageToken)) {
          $result = $this->service->queries->listqueries(
              array('pageToken' => $result->nextPageToken));
          $this->printQueries($result['queries']);
        }
        print '</pre>';
      } else {
        print '<p>No reports found</p>';
      }
    } else {
      // Call the API, getting the latest status for the passed queryId.
      $query = $this->service->queries->getquery($queryId);

      if ($query->metadata->latestReportRunTimeMs > microtime(true) * 1000 -
          self::CURRENT_REPORT_WINDOW_MS) {
        // Grab the report.
        file_put_contents($query->queryId . '.csv',
            fopen($query->metadata->googleCloudStoragePathForLatestReport,
                'r'));
        print '<p>Download complete.</p>';
      } else {
        printf('<p>No reports for query Id %s in the last 12 hours.</p>',
            $queryId);
      }
    }
  }

  /**
   * (non-PHPdoc)
   * @see BaseExample::getName()
   */
  public function getName() {
    return 'Get latest report';
  }
}

Python

#!/usr/bin/python
#
# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This example demonstrates how to retrieve the latest report.

DBM users typically create scheduled reports, where the advertiser user either
the UI or API to create a query that will be used to generate reports based on
a daily, weekly, or monthly schedule.

In this example, we check to see if a daily query has run in the last 12 hours.
If it has, we download the data to a local CSV file. If no queryId is provided,
this will print a list of existing queries.
"""

import argparse
from contextlib import closing
from datetime import datetime
from datetime import timedelta
import os
import sys
from six.moves.urllib.request import urlopen
import util

# Optional filtering arguments.
parser = argparse.ArgumentParser(
    add_help=False,
    description='Downloads a report if it has been created in '
    'the given timeframe.')
parser.add_argument(
    '--output_directory',
    default=(os.path.dirname(os.path.realpath(__file__))),
    help=('Path to the directory you want to '
          'save the report to.'))
parser.add_argument(
    '--query_id',
    default=0,
    type=int,
    help=('The id of a query used to generate a report.'))
parser.add_argument(
    '--report_window',
    default=12,
    type=int,
    help=('The age a report must be in hours at a maximum to '
          'be considered fresh.'))


def main(doubleclick_bid_manager, output_dir, query_id, report_window):
  if query_id:
    # Call the API, getting the latest status for the passed queryId.
    query = (
        doubleclick_bid_manager.queries().getquery(queryId=query_id).execute())
    try:
      # If it is recent enough...
      if (is_in_report_window(query['metadata']['latestReportRunTimeMs'],
                              report_window)):
        if not os.path.isabs(output_dir):
          output_dir = os.path.expanduser(output_dir)

        # Grab the report and write contents to a file.
        report_url = query['metadata']['googleCloudStoragePathForLatestReport']
        output_file = '%s/%s.csv' % (output_dir, query['queryId'])
        with open(output_file, 'wb') as output:
          with closing(urlopen(report_url)) as url:
            output.write(url.read())
        print('Download complete.')
      else:
        print('No reports for queryId "%s" in the last %s hours.' %
              (query['queryId'], report_window))
    except KeyError:
      print('No report found for queryId "%s".' % query_id)
  else:
    # Call the API, getting a list of queries.
    response = doubleclick_bid_manager.queries().listqueries().execute()

    # Print queries out.
    print('Id\t\tName')
    if 'queries' in response:
      # Starting with the first page.
      print_queries(response)
      # Then everything else
      while 'nextPageToken' in response and response['nextPageToken']:
        response = doubleclick_bid_manager.queries().listqueries(
            pageToken=response['nextPageToken']).execute()
        print_queries(response)
    else:
      print('No queries exist.')


def print_queries(response):
  for q in response['queries']:
    print('%s\t%s' % (q['queryId'], q['metadata']['title']))


def is_in_report_window(run_time_ms, report_window):
  """Determines if the given time in milliseconds is in the report window.

  Args:
    run_time_ms: str containing a time in milliseconds.
    report_window: int identifying the range of the report window in hours.

  Returns:
    A boolean indicating whether the given query's report run time is within
    the report window.
  """
  report_time = datetime.fromtimestamp(int((run_time_ms)) / 1000)
  earliest_time_in_range = datetime.now() - timedelta(hours=report_window)
  return report_time > earliest_time_in_range


if __name__ == '__main__':
  args = util.get_arguments(sys.argv, __doc__, parents=[parser])
  # Retrieve the query id of the report we're downloading, or set to 0.
  QUERY_ID = args.query_id
  if not QUERY_ID:
    try:
      QUERY_ID = int(
          raw_input('Enter the query id or press enter to '
                    'list queries: '))
    except ValueError:
      QUERY_ID = 0

  main(util.setup(args), args.output_directory, QUERY_ID, args.report_window)