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/perl -w
#
# Copyright 2017, 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 code example gets and downloads a criteria report from an XML
# report definition.
# Currently, there is only production support for reports download.

use strict;
use lib "../../../lib";
use utf8;

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::Reports::Predicate;
use Google::Ads::AdWords::Reports::ReportDefinition;
use Google::Ads::AdWords::Reports::Selector;
use Google::Ads::Common::ReportUtils;

use Cwd qw(abs_path);
use File::HomeDir;
use File::Spec;

# Example main subroutine.
sub download_criteria_report_with_selector {
  my $client      = shift;
  my $output_file = shift;

  # Create criteria status predicate.
  my $predicate = Google::Ads::AdWords::Reports::Predicate->new({
      field    => "Status",
      operator => "IN",
      values   => ["ENABLED", "PAUSED"]});

  # Create selector.
  my $selector = Google::Ads::AdWords::Reports::Selector->new({
      fields => [
        "CampaignId", "AdGroupId", "Id",          "CriteriaType",
        "Criteria",   "FinalUrls", "Impressions", "Clicks",
        "Cost"
      ],
      predicates => [$predicate]});

  # Create report definition.
  my (undef, undef, undef, $mday, $mon, $year) = localtime(time);
  my $today = sprintf("%d%02d%02d", ($year + 1900), ($mon + 1), $mday);

  my $report_definition = Google::Ads::AdWords::Reports::ReportDefinition->new({
      reportName     => "Last 7 days CRITERIA_PERFORMANCE_REPORT #" . $today,
      dateRangeType  => "LAST_7_DAYS",
      reportType     => "CRITERIA_PERFORMANCE_REPORT",
      downloadFormat => "CSV",
      selector       => $selector
  });

  # Optional: Modify the reporting configuration of the client to suppress
  # header, column, or summary rows in the report output and include data with
  # zero impressions. You can choose to return enum field values as enum
  # values instead of display values.
  # You can also configure this via your adwords.properties configuration file.
  $client->get_reporting_config()->set_skip_header(0);
  $client->get_reporting_config()->set_skip_column_header(0);
  $client->get_reporting_config()->set_skip_summary(0);
  $client->get_reporting_config()->set_include_zero_impressions(0);
  $client->get_reporting_config()->set_use_raw_enum_values(0);

  # Get the report handler.
  my $report_handler =
    Google::Ads::Common::ReportUtils::get_report_handler($report_definition,
    $client);

  # Download the report using the appropriate method on ReportDownloadHandler.
  my $result;
  if ($output_file) {
    $result = $report_handler->save($output_file);
  } else {
    $result = $report_handler->get_as_string();
  }

  if (!$result) {
    printf("An error has occurred of type '%s', triggered by '%s'.\n",
      $result->get_type(), $result->get_trigger());
  } elsif ($output_file) {
    printf("Report was downloaded to \"%s\".\n", $output_file);
  } else {
    printf("%s\n", $result);
  }

  return 1;
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Log SOAP XML request, response and API errors.
Google::Ads::AdWords::Logging::enable_all_logging();

# Get AdWords Client, credentials will be read from ~/adwords.properties.
my $client = Google::Ads::AdWords::Client->new({version => "v201708"});

# By default examples are set to die on any server returned fault.
$client->set_die_on_faults(1);

my $output_file =
  File::Spec->catfile(File::HomeDir->my_home, "criteria_report.csv");

# Call the example
download_criteria_report_with_selector($client, $output_file);

Download a criteria performance report with AWQL

#!/usr/bin/perl -w
#
# Copyright 2017, 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 code example gets and downloads a criteria report using an AWQL query.
# Currently, there is only production support for reports download.

use strict;
use lib "../../../lib";
use utf8;

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::Common::ReportUtils;

use Cwd qw(abs_path);
use File::HomeDir;
use File::Spec;

# Example main subroutine.
sub download_criteria_report_with_awql {
  my $client      = shift;
  my $output_file = shift;

  # Create report query.
  my (undef, undef, undef, $mday, $mon, $year) = localtime(time - 60 * 60 * 24);
  my $yesterday = sprintf("%d%02d%02d", ($year + 1900), ($mon + 1), $mday);
  (undef, undef, undef, $mday, $mon, $year) =
    localtime(time - 60 * 60 * 24 * 4);
  my $last_4_days = sprintf("%d%02d%02d", ($year + 1900), ($mon + 1), $mday);

  my $report_query =
    "SELECT CampaignId, AdGroupId, Id, Criteria, CriteriaType, " .
    "Impressions, Clicks, Cost FROM CRITERIA_PERFORMANCE_REPORT " .
    "WHERE Status IN [ENABLED, PAUSED] " . "DURING $last_4_days, $yesterday";

  # Optional: Modify the reporting configuration of the client to suppress
  # header, column, or summary rows in the report output and include data with
  # zero impressions. You can choose to return enum field values as enum
  # values instead of display values.
  # You can also configure this via your adwords.properties configuration file.
  $client->get_reporting_config()->set_skip_header(0);
  $client->get_reporting_config()->set_skip_column_header(0);
  $client->get_reporting_config()->set_skip_summary(0);
  $client->get_reporting_config()->set_include_zero_impressions(1);
  $client->get_reporting_config()->set_use_raw_enum_values(0);

  # Get the report handler.
  my $report_handler = Google::Ads::Common::ReportUtils::get_report_handler({
    query => $report_query,
    format => "CSV"
  }, $client);

  # Download the report using the appropriate method on ReportDownloadHandler.
  my $result;
  if ($output_file) {
    $result = $report_handler->save($output_file);
  } else {
    $result = $report_handler->get_as_string();
  }

  if (!$result) {
    printf("An error has occurred of type '%s', triggered by '%s'.\n",
           $result->get_type(), $result->get_trigger());
  } elsif ($output_file) {
    printf("Report was downloaded to \"%s\".\n", $output_file);
  } else {
    printf("%s\n", $result);
  }

  return 1;
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Log SOAP XML request, response and API errors.
Google::Ads::AdWords::Logging::enable_all_logging();

# Get AdWords Client, credentials will be read from ~/adwords.properties.
my $client = Google::Ads::AdWords::Client->new({version => "v201708"});

# By default examples are set to die on any server returned fault.
$client->set_die_on_faults(1);

my $output_file =
  File::Spec->catfile(File::HomeDir->my_home, "criteria_report.csv");

# Call the example
download_criteria_report_with_awql($client, $output_file);

Get report fields

#!/usr/bin/perl -w
#
# Copyright 2017, 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 gets report fields of a CRITERIA_PERFORMANCE_REPORT.

use strict;
use lib "../../../lib";
use utf8;

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;

use Cwd qw(abs_path);

# Example main subroutine.
sub get_report_fields {
  my $client = shift;

  # The type of the report to get fields for.
  my $report_type = "CRITERIA_PERFORMANCE_REPORT";

  # Get report fields.
  my $report_definition_fields =
    $client->ReportDefinitionService()
    ->getReportFields({reportType => $report_type});

  # Display report fields.
  printf "The report type \"%s\" contains the following fields:\n",
    $report_type;

  foreach my $report_definition_field (@{$report_definition_fields}) {
    printf("- %s (%s)",
      $report_definition_field->get_fieldName(),
      $report_definition_field->get_fieldType());
    if ($report_definition_field->get_enumValues()) {
      printf " := [%s]",
        join(", ", @{$report_definition_field->get_enumValues()});
    }
    print "\n";
  }

  return 1;
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Log SOAP XML request, response and API errors.
Google::Ads::AdWords::Logging::enable_all_logging();

# Get AdWords Client, credentials will be read from ~/adwords.properties.
my $client = Google::Ads::AdWords::Client->new({version => "v201708"});

# By default examples are set to die on any server returned fault.
$client->set_die_on_faults(1);

# Call the example
get_report_fields($client);

Parallel report download

#!/usr/bin/perl -w
#
# Copyright 2017, 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 gets and downloads an Ad Hoc report from an XML report
# definition for all accounts directly under a manager account.
# This example should be run against an AdWords manager account.
# NOTE: Even though this example is called parallel_report_download, this shows
# how to download the reports serially.

use strict;
use warnings;
use lib "../../../lib";
use utf8;

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::Reports::ReportDefinition;
use Google::Ads::AdWords::Reports::Selector;
use Google::Ads::Common::ReportUtils;
use Google::Ads::AdWords::v201708::Paging;
use Google::Ads::AdWords::v201708::Selector;

use Cwd qw(abs_path);
use File::Spec;
use File::Temp qw/ tempdir /;

use constant PAGE_SIZE => 500;
# Set a timeout to fail if the report is not downloaded in a specified amount
# of time.
use constant JOB_TIMEOUT_IN_MILLISECONDS => 180000;
# The time to sleep in between retries will start at this time. Then an
# exponential back-off will be instituted.
use constant JOB_BASE_WAITTIME_IN_MILLISECONDS => 10000;

# Example main subroutine.
sub parallel_report_download {
  my $client           = shift;
  my $report_directory = tempdir();

  # Retrieve all accounts under the manager account.
  my @customers = __get_all_managed_customers($client);

  # Create selector.
  my $selector = Google::Ads::AdWords::Reports::Selector->new(
    {fields => ["CampaignId", "AdGroupId", "Impressions", "Clicks", "Cost"]});

  # Create report definition.
  my $report_definition = Google::Ads::AdWords::Reports::ReportDefinition->new({
      reportName     => "Custom ADGROUP_PERFORMANCE_REPORT",
      dateRangeType  => "LAST_7_DAYS",
      reportType     => "ADGROUP_PERFORMANCE_REPORT",
      downloadFormat => "CSV",
      selector       => $selector
  });

  # Optional: Modify the reporting configuration of the client to suppress
  # header, column, or summary rows in the report output and include data with
  # zero impressions. You can choose to return enum field values as enum
  # values instead of display values.
  # You can also configure this via your adwords.properties configuration file.
  $client->get_reporting_config()->set_skip_header(0);
  $client->get_reporting_config()->set_skip_column_header(0);
  $client->get_reporting_config()->set_skip_summary(0);
  $client->get_reporting_config()->set_include_zero_impressions(0);
  $client->get_reporting_config()->set_use_raw_enum_values(0);

  printf("Downloading report for %d managed customers.\n", scalar @customers);

  my $successful_reports = {};
  my $failed_reports     = {};
  foreach my $customer_id (@customers) {
    my $output_file =
      File::Spec->catfile($report_directory,
      sprintf("adgroup_%010d.csv", $customer_id));
    $client->set_client_id($customer_id);

    # Get the report handler.
    my $report_handler =
      Google::Ads::Common::ReportUtils::get_report_handler($report_definition,
      $client);

    # If there is a failure, then retry the request.
    my $result;
    my $retries  = 0;
    my $end_time = time + JOB_TIMEOUT_IN_MILLISECONDS;
    do {
      # Download the report.
      $result = $report_handler->save($output_file);

      my $waittime_in_milliseconds =
        JOB_BASE_WAITTIME_IN_MILLISECONDS * (2**$retries);
      if (  ((time + $waittime_in_milliseconds) < $end_time)
        and !$result
        and $result->get_response_code() >= 500)
      {
        printf("Report for client customer ID %s was not downloaded" .
            " due to: %s - %s\n",
          $customer_id, $result->get_type(), $result->get_trigger());
        printf("Sleeping %d milliseconds before retrying...\n",
          $waittime_in_milliseconds);
        sleep($waittime_in_milliseconds / 1000);    # Convert to seconds.
        $retries++;
      }
    } while (time < $end_time
      and !$result
      and $result->get_response_code() >= 500);

    if (!$result) {
      printf("Report for client customer ID %s was not downloaded" .
          " due to: %s - %s\n",
        $customer_id, $result->get_type(), $result->get_trigger());
      $failed_reports->{$customer_id} = sprintf("%s: %s - %s",
        $output_file, $result->get_type(), $result->get_trigger());
    } else {
      printf(
        "Report for client customer ID %s successfully downloaded to: %s\n",
        $customer_id, $output_file);
      $successful_reports->{$customer_id} = $output_file;
    }
  }

  printf("All downloads completed. Results:\n");
  printf("Successful reports:\n");
  foreach my $client_customer_id (keys $successful_reports) {
    printf("\tClient ID %s => '%s'\n",
      $client_customer_id, $successful_reports->{$client_customer_id});
  }
  printf("Failed reports:\n");
  foreach my $client_customer_id (keys $failed_reports) {
    printf("\tClient ID %s => '%s'\n",
      $client_customer_id, $failed_reports->{$client_customer_id});
  }
  printf("End of results.");

  return 1;
}

# Retrieve all the customers under a manager account.
sub __get_all_managed_customers {
  my ($client) = @_;

  # Create selector.
  my $paging = Google::Ads::AdWords::v201708::Paging->new({
      startIndex    => 0,
      numberResults => PAGE_SIZE
  });
  my $predicate = Google::Ads::AdWords::v201708::Predicate->new({
      field    => "CanManageClients",
      operator => "EQUALS",
      values   => "false"
  });
  my $selector = Google::Ads::AdWords::v201708::Selector->new({
      fields     => ["CustomerId"],
      paging     => $paging,
      predicates => [$predicate]});

  my $page;
  my @customers = ();
  do {
    $page =
      $client->ManagedCustomerService()->get({serviceSelector => $selector});

    if ($page->get_entries()) {
      foreach my $customer (@{$page->get_entries()}) {
        push @customers, $customer->get_customerId();
      }
    }
    $paging->set_startIndex($paging->get_startIndex() + PAGE_SIZE);
  } while ($paging->get_startIndex() < $page->get_totalNumEntries());

  return @customers;
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Log SOAP XML request, response and API errors.
Google::Ads::AdWords::Logging::enable_all_logging();

# Get AdWords Client, credentials will be read from ~/adwords.properties.
my $client = Google::Ads::AdWords::Client->new({version => "v201708"});

# By default examples are set to die on any server returned fault.
$client->set_die_on_faults(1);

# Call the example
parallel_report_download($client);

Stream criteria report results

#!/usr/bin/perl -w
#
# Copyright 2017, 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 streams the result of an ad hoc report, collecting total
# impressions by campaign for each line. This demonstrates how you can extract
# data from a large report without holding the entire result set in memory
# or using files.

use strict;
use lib "../../../lib";
use utf8;

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::Common::ReportUtils;

use Cwd qw(abs_path);

# Example main subroutine.
sub stream_criteria_report_results {
  my $client = shift;

  my $report_query =
    "SELECT Id, AdNetworkType1, Impressions " .
    "FROM CRITERIA_PERFORMANCE_REPORT WHERE Status IN [ENABLED, PAUSED] " .
    "DURING LAST_7_DAYS";

  # Optional: Set the reporting configuration of the session to suppress
  # header, column name, or summary rows in the report output. You can also
  # configure this via your adwords.properties configuration file.
  # In addition, you can set whether you want to explicitly include or
  # exclude zero impression rows and you can set whether to return enum values
  # or display values for enum fields.
  $client->get_reporting_config()->set_skip_header(1);
  $client->get_reporting_config()->set_skip_column_header(1);
  $client->get_reporting_config()->set_skip_summary(1);
  $client->get_reporting_config()->set_include_zero_impressions(0);
  $client->get_reporting_config()->set_use_raw_enum_values(0);

  # Get the report handler.
  my $report_handler = Google::Ads::Common::ReportUtils::get_report_handler({
      query  => $report_query,
      format => "CSV"
    },
    $client
  );

  # Pass in the anonymous subroutine that will be called as data is available
  # for processing.
  my %impressions_by_ad_network_type1 = ();
  my $incomplete_line                 = '';
  my $result                          = $report_handler->process_contents(
    sub {
      my ($data, $response) = @_;
      # If the line is starting in the middle, then prepend the incomplete line
      # from last time.
      $data            = $incomplete_line . $data;
      $incomplete_line = '';
      # Match the line that is ID,AdNetworkType1,Impressions
      # Example: 123456,Search Network,5
      while ($data =~ /(\d+),([^,]+),(\d+)\n/g) {
        my ($ad_network_type1, $impressions) = ($2, $3);
        my $impressions_total =
          $impressions_by_ad_network_type1{$ad_network_type1};
        $impressions_total =
          (defined($impressions_total)) ? $impressions_total : 0;
        $impressions_by_ad_network_type1{$ad_network_type1} =
          $impressions_total + $impressions;
      }
      # If everything wasn't processed, then save off the incomplete line to
      # be prepended the next time this subroutine is called.
      if ($data =~ /\n(.*)$/) {
        $incomplete_line = $1;
      }
    });

  if (!$result) {
    printf("An error has occurred of type '%s', triggered by '%s'.\n",
      $result->get_type(), $result->get_trigger());
    return 1;
  }

  # Print the impression totals by ad network type 1.
  print("Total impressions by ad network type 1:\n");
  while (my ($key, $val) = each %impressions_by_ad_network_type1) {
    printf "$key\t$val\n";
  }

  return 1;
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Log SOAP XML request, response and API errors.
Google::Ads::AdWords::Logging::enable_all_logging();

# Get AdWords Client, credentials will be read from ~/adwords.properties.
my $client = Google::Ads::AdWords::Client->new({version => "v201708"});

# By default examples are set to die on any server returned fault.
$client->set_die_on_faults(1);

# Call the example.
stream_criteria_report_results($client);

Send feedback about...

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