Reporting Samples

The code samples below provide examples of common reporting functions using the AdWords API. Client Library.

Download a criteria performance report with selector

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
#
# License:: 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 gets and downloads an Ad Hoc report from a XML report definition.

require 'adwords_api'

def download_criteria_report_with_selector(file_name)
  # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml
  # when called without parameters.
  adwords = AdwordsApi::Api.new

  # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
  # the configuration file or provide your own logger:
  # adwords.logger = Logger.new('adwords_xml.log')

  # Get report utilities for the version.
  report_utils = adwords.report_utils(API_VERSION)

  # Define report definition. You can also pass your own XML text as a string.
  report_definition = {
    :selector => {
      :fields => ['CampaignId', 'AdGroupId', 'Id', 'Criteria', 'CriteriaType',
          'FinalUrls', 'Impressions', 'Clicks', 'Cost'],
      # Predicates are optional.
      :predicates => {
        :field => 'Status',
        :operator => 'IN',
        :values => ['ENABLED', 'PAUSED']
      }
    },
    :report_name => 'Last 7 days CRITERIA_PERFORMANCE_REPORT',
    :report_type => 'CRITERIA_PERFORMANCE_REPORT',
    :download_format => 'CSV',
    :date_range_type => 'LAST_7_DAYS',
  }

  # Optional: Set the configuration of the API instance to suppress header,
  # column name, or summary rows in the report output. You can also configure
  # this in your adwords_api.yml configuration file.
  adwords.skip_report_header = false
  adwords.skip_column_header = false
  adwords.skip_report_summary = false
  # Enable to allow rows with zero impressions to show.
  adwords.include_zero_impressions = false

  # Download report, using "download_report_as_file" utility method.
  # To retrieve the report as return value, use "download_report" method.
  report_utils.download_report_as_file(report_definition, file_name)
  puts "Report was downloaded to '%s'." % file_name
end

if __FILE__ == $0
  API_VERSION = :v201708

  begin
    # File name to write report to.
    file_name = 'INSERT_OUTPUT_FILE_NAME_HERE'
    download_criteria_report_with_selector(file_name)

  # Authorization error.
  rescue AdsCommon::Errors::OAuth2VerificationRequired => e
    puts "Authorization credentials are not valid. Edit adwords_api.yml for " +
        "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " +
        "to retrieve and store OAuth2 tokens."
    puts "See this wiki page for more details:\n\n  " +
        'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2'

  # HTTP errors.
  rescue AdsCommon::Errors::HttpError => e
    puts "HTTP Error: %s" % e

  # API errors.
  rescue AdwordsApi::Errors::ReportError => e
    puts "Reporting Error: %s" % e.message
  end
end

Download a criteria performance report with AWQL

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright:: Copyright 2012, Google Inc. All Rights Reserved.
#
# License:: 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 gets an Ad Hoc report using AdWords Query Language.
# See AWQL guide for more details:
#   https://developers.google.com/adwords/api/docs/guides/awql

require 'date'

require 'adwords_api'

def download_criteria_report_with_awql(file_name, report_format)
  # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml
  # when called without parameters.
  adwords = AdwordsApi::Api.new

  # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
  # the configuration file or provide your own logger:
  # adwords.logger = Logger.new('adwords_xml.log')

  # Get report utilities for the version.
  report_utils = adwords.report_utils(API_VERSION)

  # Prepare a date range for the last week. Instead you can use 'LAST_7_DAYS'.
  date_range = '%s,%s' % [
      DateTime.parse((Date.today - 7).to_s).strftime('%Y%m%d'),
      DateTime.parse((Date.today - 1).to_s).strftime('%Y%m%d')
  ]

  # Define report definition. You can also pass your own XML text as a string.
  report_query = 'SELECT CampaignId, AdGroupId, Id, Criteria, CriteriaType, ' +
      'Impressions, Clicks, Cost FROM CRITERIA_PERFORMANCE_REPORT ' +
      'WHERE Status IN [ENABLED, PAUSED] ' +
      'DURING %s' % date_range

  # Optional: Set the configuration of the API instance to suppress header,
  # column name, or summary rows in the report output. You can also configure
  # this in your adwords_api.yml configuration file.
  adwords.skip_report_header = false
  adwords.skip_column_header = false
  adwords.skip_report_summary = false
  # Enable to allow rows with zero impressions to show.
  adwords.include_zero_impressions = true

  # Download report, using "download_report_as_file_with_awql" utility method.
  # To retrieve the report as return value, use "download_report_with_awql"
  # method.
  report_utils.download_report_as_file_with_awql(report_query, report_format,
                                                 file_name)
  puts "Report was downloaded to '%s'." % file_name
end

if __FILE__ == $0
  API_VERSION = :v201708

  begin
    # File name to write report to.
    file_name = 'INSERT_OUTPUT_FILE_NAME_HERE'
    report_format = 'CSV'
    download_criteria_report_with_awql(file_name, report_format)

  # Authorization error.
  rescue AdsCommon::Errors::OAuth2VerificationRequired => e
    puts "Authorization credentials are not valid. Edit adwords_api.yml for " +
        "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " +
        "to retrieve and store OAuth2 tokens."
    puts "See this wiki page for more details:\n\n  " +
        'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2'

  # HTTP errors.
  rescue AdsCommon::Errors::HttpError => e
    puts 'HTTP Error: %s' % e

  # API errors.
  rescue AdwordsApi::Errors::ReportError => e
    puts 'Reporting Error: %s' % e.message
  end
end

Get report fields

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
#
# License:: 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 gets the list of possible report fields for a report type.

require 'adwords_api'

def get_report_fields(report_type)
  # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml
  # when called without parameters.
  adwords = AdwordsApi::Api.new

  # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
  # the configuration file or provide your own logger:
  # adwords.logger = Logger.new('adwords_xml.log')

  report_def_srv = adwords.service(:ReportDefinitionService, API_VERSION)

  # Get report fields.
  fields = report_def_srv.get_report_fields(report_type)
  if fields
    puts "Report type '%s' contains the following fields:" % report_type
    fields.each do |field|
      puts ' - %s (%s)' % [field[:field_name], field[:field_type]]
      puts '  := [%s]' % field[:enum_values].join(', ') if field[:enum_values]
    end
  end
end

if __FILE__ == $0
  API_VERSION = :v201708

  begin
    report_type = 'INSERT_REPORT_TYPE_HERE'
    get_report_fields(report_type)

  # Authorization error.
  rescue AdsCommon::Errors::OAuth2VerificationRequired => e
    puts "Authorization credentials are not valid. Edit adwords_api.yml for " +
        "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " +
        "to retrieve and store OAuth2 tokens."
    puts "See this wiki page for more details:\n\n  " +
        'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2'

  # HTTP errors.
  rescue AdsCommon::Errors::HttpError => e
    puts "HTTP Error: %s" % e

  # API errors.
  rescue AdwordsApi::Errors::ApiException => e
    puts "Message: %s" % e.message
    puts 'Errors:'
    e.errors.each_with_index do |error, index|
      puts "\tError [%d]:" % (index + 1)
      error.each do |field, value|
        puts "\t\t%s: %s" % [field, value]
      end
    end
  end
end

Parallel report download

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright:: Copyright 2011, Google Inc. All Rights Reserved.
#
# License:: 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 gets and downloads an Ad Hoc report from a XML report definition
# for all accounts in hierarchy in multiple parallel threads. This example
# needs to be run against an AdWords manager account.

require 'thread'

require 'adwords_api'
require 'adwords_api/utils'

def parallel_report_download()
  # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml
  # when called without parameters.
  adwords = AdwordsApi::Api.new

  # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
  # the configuration file or provide your own logger:
  # adwords.logger = Logger.new('adwords_xml.log')

  # Determine list of customer IDs to retrieve report for. For this example we
  # will use ManagedCustomerService to get all IDs in hierarchy.

  managed_customer_srv = adwords.service(:ManagedCustomerService, API_VERSION)

  # Get the account hierarchy for this account.
  selector = {:fields => ['CustomerId']}

  graph = managed_customer_srv.get(selector)

  # Using queue to balance load between threads.
  queue = Queue.new()

  if graph and graph[:entries] and !graph[:entries].empty?
    graph[:entries].each {|account| queue << account[:customer_id]}
  else
    raise StandardError, 'Can not retrieve any customer ID'
  end

  # Get report utilities for the version.
  report_utils = adwords.report_utils(API_VERSION)

  # Define report definition. You can also pass your own XML text as a string.
  report_definition = {
    :selector => {
        :fields => ['CampaignId', 'AdGroupId', 'Impressions', 'Clicks', 'Cost'],
        # Predicates are optional.
        :predicates => {
          :field => 'AdGroupStatus',
          :operator => 'IN',
          :values => ['ENABLED', 'PAUSED']
        }
      },
      :report_name => 'Custom ADGROUP_PERFORMANCE_REPORT',
      :report_type => 'ADGROUP_PERFORMANCE_REPORT',
      :download_format => 'CSV',
      :date_range_type => 'LAST_7_DAYS'
  }

  puts 'Retrieving %d reports with %d threads:' % [queue.size, THREADS]

  reports_succeeded = Queue.new()
  reports_failed = Queue.new()

  # Creating a mutex to control access to the queue.
  queue_mutex = Mutex.new

  # Start all the threads.
  threads = (1..THREADS).map do |thread_id|
    Thread.new(report_definition) do |local_def|
      cid = nil
      begin
        cid = queue_mutex.synchronize {(queue.empty?) ? nil : queue.pop(true)}
        if cid
          retry_count = 0
          file_name = 'adgroup_%010d.csv' % cid
          puts "[%2d/%d] Loading report for customer ID %s into '%s'..." %
              [thread_id, retry_count,
               AdwordsApi::Utils.format_id(cid), file_name]
          begin
            report_utils.download_report_as_file(local_def, file_name, cid)
            reports_succeeded << {:cid => cid, :file_name => file_name}
          rescue AdwordsApi::Errors::ReportError => e
            if e.http_code == 500 && retry_count < MAX_RETRIES
              retry_count += 1
              sleep(retry_count * BACKOFF_FACTOR)
              retry
            else
              puts(('Report failed for customer ID %s with code %d after %d ' +
                  'retries.') % [cid, e.http_code, retry_count + 1])
              reports_failed <<
                {:cid => cid, :http_code => e.http_code, :message => e.message}
            end
          end
        end
      end while (cid != nil)
    end
  end

  # Wait for all threads to finish.
  threads.each { |aThread|  aThread.join }

  puts 'Download completed, results:'
  puts 'Successful reports:'
  while !reports_succeeded.empty? do
    result = reports_succeeded.pop()
    puts "\tClient ID %s => '%s'" %
        [AdwordsApi::Utils.format_id(result[:cid]), result[:file_name]]
  end
  puts 'Failed reports:'
  while !reports_failed.empty? do
    result = reports_failed.pop()
    puts "\tClient ID %s => Code: %d, Message: '%s'" %
        [AdwordsApi::Utils.format_id(result[:cid]),
         result[:http_code], result[:message]]
  end
  puts 'End of results.'
end

if __FILE__ == $0
  API_VERSION = :v201708
  # Number of parallel threads to spawn.
  THREADS = 10
  # Maximum number of retries for 500 errors.
  MAX_RETRIES = 5
  # Timeout between retries in seconds.
  BACKOFF_FACTOR = 5

  begin
    parallel_report_download()

  # Authorization error.
  rescue AdsCommon::Errors::OAuth2VerificationRequired => e
    puts "Authorization credentials are not valid. Edit adwords_api.yml for " +
        "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " +
        "to retrieve and store OAuth2 tokens."
    puts "See this wiki page for more details:\n\n  " +
        'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2'

  # HTTP errors.
  rescue AdsCommon::Errors::HttpError => e
    puts 'HTTP Error: %s' % e

  # API errors.
  rescue AdwordsApi::Errors::ReportError => e
    puts 'Reporting Error: %s' % e.message
  end
end

Stream criteria report results

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright:: Copyright 2015, Google Inc. All Rights Reserved.
#
# License:: 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 streams the results of an Ad Hoc report to a file.

require 'adwords_api'

def stream_criteria_report_results()
  # AdwordsApi::Api will read a config file from ENV['HOME']/adwords_api.yml
  # when called without parameters.
  adwords = AdwordsApi::Api.new

  # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
  # the configuration file or provide your own logger:
  # adwords.logger = Logger.new('adwords_xml.log')

  # Get report utilities for the version.
  report_utils = adwords.report_utils(API_VERSION)

  # Define report query.
  report_query = 'SELECT Id, AdNetworkType1, Impressions ' +
      'FROM CRITERIA_PERFORMANCE_REPORT ' +
      'WHERE Status IN [ENABLED, PAUSED] ' +
      'DURING LAST_7_DAYS'

  # Optional: Set the configuration of the API instance to suppress header,
  # column name, or summary rows in the report output. You can also configure
  # this in your adwords_api.yml configuration file.
  adwords.skip_report_header = true
  adwords.skip_column_header = true
  adwords.skip_report_summary = true
  # Enable to allow rows with zero impressions to show.
  adwords.include_zero_impressions = false

  # Set the default value of the hash to 0 to allow easy totaling.
  ad_network_map = Hash.new(0)

  # We use get_stream_helper_with_awql.each_line here, which uses the
  # ReportStream utility to handle breaking the streamed results into lines
  # for easy processing. If you'd rather handle processing yourself, you can
  # use download_report_as_stream_with_awql, which just passes data to the
  # block as it's downloaded, without breaking it up into meaningful chunks.
  report_utils.get_stream_helper_with_awql(
        report_query, 'CSV').each_line do |line|
    process_line(line, ad_network_map)
  end

  puts 'Total impressions by ad network type 1:'
  ad_network_map.each do |ad_network_type, total_impressions|
    puts '  %s: %s' % [ad_network_type, total_impressions]
  end
end

def process_line(line, ad_network_map)
  id, ad_network_type_1, impressions = line.split(',')
  ad_network_map[ad_network_type_1] += impressions.to_i
end

if __FILE__ == $0
  API_VERSION = :v201708

  begin
    # File name to write report to.
    stream_criteria_report_results()

  # Authorization error.
  rescue AdsCommon::Errors::OAuth2VerificationRequired => e
    puts "Authorization credentials are not valid. Edit adwords_api.yml for " +
        "OAuth2 client ID and secret and run misc/setup_oauth2.rb example " +
        "to retrieve and store OAuth2 tokens."
    puts "See this wiki page for more details:\n\n  " +
        'https://github.com/googleads/google-api-ads-ruby/wiki/OAuth2'

  # HTTP errors.
  rescue AdsCommon::Errors::HttpError => e
    puts "HTTP Error: %s" % e

  # API errors.
  rescue AdwordsApi::Errors::ReportError => e
    puts "Reporting Error: %s" % e.message
  end
end

Send feedback about...

AdWords API
AdWords API
Need help? Visit our support page.