Optimization Samples

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

Estimate keyword traffic

#!/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 keyword traffic estimates.

use strict;

use lib "../../../lib";

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201710::AdGroupEstimateRequest;
use Google::Ads::AdWords::v201710::CampaignEstimateRequest;
use Google::Ads::AdWords::v201710::Keyword;
use Google::Ads::AdWords::v201710::KeywordEstimateRequest;
use Google::Ads::AdWords::v201710::Language;
use Google::Ads::AdWords::v201710::Location;
use Google::Ads::AdWords::v201710::TrafficEstimatorSelector;

use Cwd qw(abs_path);

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

  # Create keywords. Refer to the TrafficEstimatorService documentation for
  # the maximum number of keywords that can be passed in a single request.
  # https://developers.google.com/adwords/api/docs/reference/latest/TrafficEstimatorService
  my @keywords = (
    Google::Ads::AdWords::v201710::Keyword->new({
        text      => "mars cruise",
        matchType => "BROAD"
      }
    ),
    Google::Ads::AdWords::v201710::Keyword->new({
        text      => "cheap cruise",
        matchType => "PHRASE"
      }
    ),
    Google::Ads::AdWords::v201710::Keyword->new({
        text      => "cruise",
        matchType => "EXACT"
      }));

  my @negative_keywords = (
    Google::Ads::AdWords::v201710::Keyword->new({
        text      => "moon walk",
        matchType => "BROAD"
      }));

  # Create a keyword estimate request for each keyword.
  my @keyword_estimate_requests;
  foreach my $keyword (@keywords) {
    push @keyword_estimate_requests,
      Google::Ads::AdWords::v201710::KeywordEstimateRequest->new(
      {keyword => $keyword,});
  }
  foreach my $keyword (@negative_keywords) {
    push @keyword_estimate_requests,
      Google::Ads::AdWords::v201710::KeywordEstimateRequest->new({
        keyword    => $keyword,
        isNegative => 1
      });
  }

  # Create ad group estimate requests.
  my $ad_group_estimate_request =
    Google::Ads::AdWords::v201710::AdGroupEstimateRequest->new({
      keywordEstimateRequests => \@keyword_estimate_requests,
      maxCpc =>
        Google::Ads::AdWords::v201710::Money->new({microAmount => 1000000})});

  my $location = Google::Ads::AdWords::v201710::Location->new({
      id => "2840"    # US - see http://goo.gl/rlrFr
  });
  my $language = Google::Ads::AdWords::v201710::Language->new({
      id => "1000"    # en - see http://goo.gl/LvMmS
  });

  # Create campaign estimate requests.
  my $campaign_estimate_request =
    Google::Ads::AdWords::v201710::CampaignEstimateRequest->new({
      adGroupEstimateRequests => [$ad_group_estimate_request],
      criteria                => [$location, $language]});

  # Optional: Request a list of campaign level estimates segmented by platform.
  my $platform_estimate_request = "1";

  # Create selector.
  my $selector = Google::Ads::AdWords::v201710::TrafficEstimatorSelector->new({
      campaignEstimateRequests  => [$campaign_estimate_request],
      platformEstimateRequested => [$platform_estimate_request]});

  # Get traffic estimates.
  my $result = $client->TrafficEstimatorService()->get({selector => $selector});

  # Display traffic estimates.
  if ($result) {
    my $campaign_estimates = $result->get_campaignEstimates();
    if ($campaign_estimates) {
      # Display the campaign level estimates segmented by platform.
      foreach my $campaign_estimate (@{$campaign_estimates}) {
        if ($campaign_estimate->get_platformEstimates()) {
          foreach
            my $platform_estimate (@{$campaign_estimate->get_platformEstimates()})
          {
            my $platform_message = sprintf(
              "Results for the platform with ID: %d and name : %s",
              $platform_estimate->get_platform()->get_id(),
              $platform_estimate->get_platform()->get_platformName());
            display_mean_estimates(
              $platform_message,
              $platform_estimate->get_minEstimate(),
              $platform_estimate->get_maxEstimate());
          }
        }

        if ($campaign_estimate->get_adGroupEstimates()) {
          my $keyword_estimates =
            $campaign_estimate->get_adGroupEstimates()->[0]
            ->get_keywordEstimates();
          for (my $i = 0 ; $i < scalar(@{$keyword_estimates}) ; $i++) {
            # Negative keywords don't generate estimates but instead affect
            # estimates of your other keywords, the following condition just
            # skips printing out estimates for a negative keyword.
            if ($keyword_estimate_requests[$i]->get_isNegative()) {
              next;
            }

            my $keyword = $keyword_estimate_requests[$i]->get_keyword();
            my $keyword_estimate = $keyword_estimates->[$i];
            my $keyword_message =
              sprintf
              "Results for the keyword with text '%s' and match type '%s':\n",
              $keyword->get_text(), $keyword->get_matchType();
            display_mean_estimates(
              $keyword_message,
              $keyword_estimate->get_min(),
              $keyword_estimate->get_max());
          }
        }
      }
    }
  } else {
    print "No traffic estimates were returned.\n";
  }
  return 1;
}

# Display the mean estimates.
sub display_mean_estimates {
  my ($message, $min_estimate, $max_estimate) = @_;

  # Find the mean of the min and max values.
  my $mean_average_cpc = calculate_money_mean($min_estimate->get_averageCpc(),
    $max_estimate->get_averageCpc());
  my $mean_average_position = calculate_mean(
    $min_estimate->get_averagePosition(),
    $max_estimate->get_averagePosition());
  my $mean_clicks = calculate_mean($min_estimate->get_clicksPerDay(),
    $max_estimate->get_clicksPerDay());
  my $mean_total_cost = calculate_money_mean($min_estimate->get_totalCost(),
    $max_estimate->get_totalCost());

  printf "%s:\n",                            $message;
  printf "  Estimated average CPC: %.2f\n",  $mean_average_cpc;
  printf "  Estimated ad position: %.2f\n",  $mean_average_position;
  printf "  Estimated daily clicks: %.2f\n", $mean_clicks;
  printf "  Estimated daily cost: %.2f\n\n", $mean_total_cost;
}

# Calculates the mean microAmount of two Money objects if neither is
# null, else returns NaN.
sub calculate_money_mean {
  my ($min_money, $max_money) = @_;

  if ($min_money && $max_money) {
    return calculate_mean($min_money->get_microAmount(),
      $max_money->get_microAmount());
  }
  return 'NaN';
}

# Calculates the mean of two numbers if neither is null, else returns NaN.
sub calculate_mean {
  my ($min, $max) = @_;

  if (defined($min) && defined($max)) {
    return ($min + $max) / 2;
  }
  return 'NaN';
}

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

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

# Call the example
estimate_keyword_traffic($client);

Get campaign criterion bid modifier simulations

#!/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 all available campaign mobile bid modifier landscapes
# for a given campaign.
# To get campaigns, run basic_operations/get_campaigns.pl.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201710::OrderBy;
use Google::Ads::AdWords::v201710::Paging;
use Google::Ads::AdWords::v201710::Predicate;
use Google::Ads::AdWords::v201710::Selector;

use Cwd qw(abs_path);

use constant PAGE_SIZE => 100;

# Replace with a valid value of your account.
my $campaign_id = "INSERT_CAMPAIGN_ID_HERE";

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

  # Create predicates.
  my $campaign_predicate = Google::Ads::AdWords::v201710::Predicate->new({
      field    => "CampaignId",
      operator => "IN",
      values   => [$campaign_id]});
  # Create selector.
  my $paging = Google::Ads::AdWords::v201710::Paging->new({
    startIndex    => 0,
    numberResults => PAGE_SIZE
  });
  my $selector = Google::Ads::AdWords::v201710::Selector->new({
      fields => [
        "BidModifier",           "CampaignId",
        "CriterionId",           "StartDate",
        "EndDate",               "LocalClicks",
        "LocalCost",             "LocalImpressions",
        "TotalLocalClicks",      "TotalLocalCost",
        "TotalLocalImpressions", "RequiredBudget"
      ],
      paging     => $paging,
      predicates => [$campaign_predicate]});

  # Display bid landscapes.
  my $landscape_points_in_previous_page = 0;
  my $start_index                       = 0;
  do {
    # Offset the start index by the number of landscape points in the last
    # retrieved page, NOT the number of entries (bid landscapes) in the page.
    $start_index += $landscape_points_in_previous_page;
    $selector->get_paging()->set_startIndex($start_index);

    # Reset the count of landscape points in preparation for processing the
    # next page.
    $landscape_points_in_previous_page = 0;

    # Request the next page of bid landscapes.
    my $page =
      $client->DataService()
      ->getCampaignCriterionBidLandscape({serviceSelector => $selector});

    if ($page->get_entries()) {
      foreach my $criterion_bid_landscape (@{$page->get_entries()}) {
        printf "Found campaign-level criterion bid modifier landscapes for" .
          " criterion with ID %d, start date '%s', end date '%s', and" .
          " landscape points:\n",
          $criterion_bid_landscape->get_criterionId(),
          $criterion_bid_landscape->get_startDate(),
          $criterion_bid_landscape->get_endDate();
        my @landscape_points = @{$criterion_bid_landscape
          ->get_landscapePoints()};
        foreach my $landscape_point (@landscape_points) {
          $landscape_points_in_previous_page++;
          printf "  bid modifier: %.2f => clicks: %d, cost: %.0f, " .
            "impressions: %d, total clicks: %d, total cost: %.0f, " .
            "total impressions: %d, and required budget: %.0f\n",
            $landscape_point->get_bidModifier(),
            $landscape_point->get_clicks(),
            $landscape_point->get_cost()->get_microAmount(),
            $landscape_point->get_impressions(),
            $landscape_point->get_totalLocalClicks(),
            $landscape_point->get_totalLocalCost()->get_microAmount(),
            $landscape_point->get_totalLocalImpressions(),
            $landscape_point->get_requiredBudget()->get_microAmount();
        }
      }
    }
  } while ($landscape_points_in_previous_page >= PAGE_SIZE);

  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 => "v201710"});

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

# Call the example
get_campaign_criterion_bid_modifier_simulations($client, $campaign_id);


Get keyword bid simulations

#!/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 bid landscapes for a keywords. To get keywords, run
# basic_operations/get_keywords.pl.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201710::OrderBy;
use Google::Ads::AdWords::v201710::Paging;
use Google::Ads::AdWords::v201710::Predicate;
use Google::Ads::AdWords::v201710::Selector;

use Cwd qw(abs_path);

use constant PAGE_SIZE => 100;

# Replace with valid values of your account.
my $ad_group_id = "INSERT_AD_GROUP_ID_HERE";
my $keyword_id  = "INSERT_CRITERION_ID_HERE";

# Example main subroutine.
sub get_keyword_bid_simulations {
  my ($client, $ad_group_id, $keyword_id) = @_;

  # Create predicates.
  my $adgroup_predicate = Google::Ads::AdWords::v201710::Predicate->new({
      field    => "AdGroupId",
      operator => "IN",
      values   => [$ad_group_id]});
  my $criterion_predicate = Google::Ads::AdWords::v201710::Predicate->new({
      field    => "CriterionId",
      operator => "IN",
      values   => [$keyword_id]});

  # Create selector.
  my $paging = Google::Ads::AdWords::v201710::Paging->new({
    startIndex    => 0,
    numberResults => PAGE_SIZE
  });
  my $selector = Google::Ads::AdWords::v201710::Selector->new({
      fields => [
        "AdGroupId", "CriterionId", "StartDate", "EndDate",
        "Bid",       "LocalClicks", "LocalCost", "LocalImpressions"
      ],
      paging     => $paging,
      predicates => [$adgroup_predicate, $criterion_predicate]});

  # Display bid landscapes.
  my $landscape_points_in_previous_page = 0;
  my $start_index                       = 0;
  do {
    # Offset the start index by the number of landscape points in the last
    # retrieved page, NOT the number of entries (bid landscapes) in the page.
    $start_index += $landscape_points_in_previous_page;
    $selector->get_paging()->set_startIndex($start_index);

    # Reset the count of landscape points in preparation for processing the
    # next page.
    $landscape_points_in_previous_page = 0;

    # Request the next page of bid landscapes.
    my $page =
      $client->DataService()
      ->getCampaignCriterionBidLandscape({serviceSelector => $selector});

    if ($page->get_entries()) {
      foreach my $criterion_bid_landscape (@{$page->get_entries()}) {
        printf "Criterion bid landscape with ad group ID %d, criterion ID " .
          " %d, start date %s, end date %s, with landscape points:\n",
          $criterion_bid_landscape->get_criterionId(),
          $criterion_bid_landscape->get_startDate(),
          $criterion_bid_landscape->get_endDate();
        foreach my $bid_landscape_point (
          @{$criterion_bid_landscape->get_landscapePoints()})
        {
          $landscape_points_in_previous_page++;
          printf "\t{bid: %d clicks: %d cost: %d impressions: %d}\n",
            $bid_landscape_point->get_bid()->get_microAmount(),
            $bid_landscape_point->get_clicks(),
            $bid_landscape_point->get_cost()->get_microAmount(),
            $bid_landscape_point->get_impressions();
        }
        printf(" was found.");
      }
    }
  } while ($landscape_points_in_previous_page >= PAGE_SIZE);
  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 => "v201710"});

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

# Call the example
get_keyword_bid_simulations($client, $ad_group_id, $keyword_id);

Get keyword ideas

#!/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 keywords related to a list of seed keywords.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201710::Language;
use Google::Ads::AdWords::v201710::LanguageSearchParameter;
use Google::Ads::AdWords::v201710::NetworkSearchParameter;
use Google::Ads::AdWords::v201710::NetworkSetting;
use Google::Ads::AdWords::v201710::Paging;
use Google::Ads::AdWords::v201710::RelatedToQuerySearchParameter;
use Google::Ads::AdWords::v201710::SeedAdGroupIdSearchParameter;
use Google::Ads::AdWords::v201710::TargetingIdeaSelector;
use Google::Ads::Common::MapUtils;

use Cwd qw(abs_path);

# Replace with valid values of your account.
# If you do not want to use an existing ad group to seed your request, you can
# set this to undef.
my $ad_group_id = "INSERT_AD_GROUP_ID_HERE";

# Example main subroutine.
sub get_keyword_ideas {
  my ($client, $ad_group_id) = @_;

  # Create selector.
  my $selector = Google::Ads::AdWords::v201710::TargetingIdeaSelector->new({
    requestType => "IDEAS",
    ideaType    => "KEYWORD"
  });
  $selector->set_requestedAttributeTypes([
    "KEYWORD_TEXT", "SEARCH_VOLUME",
    "AVERAGE_CPC",  "COMPETITION",
    "CATEGORY_PRODUCTS_AND_SERVICES"
  ]);

  # Create related to query search parameter.
  my @search_parameters = ();
  my $related_to_query_search_parameter =
    Google::Ads::AdWords::v201710::RelatedToQuerySearchParameter->new(
    {queries => ["bakery", "pastries", "birthday cake"]});
  push @search_parameters, $related_to_query_search_parameter;

  # Set selector paging (required for targeting idea service).
  my $paging = Google::Ads::AdWords::v201710::Paging->new({
    startIndex    => 0,
    numberResults => 10
  });
  $selector->set_paging($paging);

  # Language setting (not-required).
  # The ID can be found in the documentation:
  #   https://developers.google.com/adwords/api/docs/appendix/languagecodes
  my $language_english =
    Google::Ads::AdWords::v201710::Language->new({id => 1000});
  my $language_search_parameter =
    Google::Ads::AdWords::v201710::LanguageSearchParameter->new(
    {languages => [$language_english]});
  push @search_parameters, $language_search_parameter;

  # Create network search paramter (optional).
  my $network_setting = Google::Ads::AdWords::v201710::NetworkSetting->new({
    targetGoogleSearch         => 1,
    targetSearchNetwork        => 0,
    targetContentNetwork       => 0,
    targetPartnerSearchNetwork => 0
  });
  my $network_setting_parameter =
    Google::Ads::AdWords::v201710::NetworkSearchParameter->new(
    {networkSetting => $network_setting});
  push @search_parameters, $network_setting_parameter;

  # Optional: Use an existing ad group to generate ideas.
  if ($ad_group_id) {
    my $seed_ad_group_id_search_parameter =
      Google::Ads::AdWords::v201710::SeedAdGroupIdSearchParameter->new({
        adGroupId => $ad_group_id
      });
    push @search_parameters, $seed_ad_group_id_search_parameter;
  }

  $selector->set_searchParameters(\@search_parameters);

  # Get keyword ideas.
  my $page = $client->TargetingIdeaService()->get({selector => $selector});

  # Display keyword ideas.
  if ($page->get_entries()) {
    foreach my $targeting_idea (@{$page->get_entries()}) {
      my $data =
        Google::Ads::Common::MapUtils::get_map($targeting_idea->get_data());
      my $keyword = $data->{"KEYWORD_TEXT"}->get_value();
      my $search_volume =
          $data->{"SEARCH_VOLUME"}->get_value()
        ? $data->{"SEARCH_VOLUME"}->get_value()
        : 0;
      my $categories =
          $data->{"CATEGORY_PRODUCTS_AND_SERVICES"}->get_value()
        ? $data->{"CATEGORY_PRODUCTS_AND_SERVICES"}->get_value()
        : [];
      my $average_cpc =
        $data->{"AVERAGE_CPC"}->get_value()->get_microAmount();
      my $competition = $data->{"COMPETITION"}->get_value();
      printf "Keyword with text '%s', monthly search volume %d, average CPC" .
        " %d, and competition %.2f was found with categories: '%s'\n", $keyword,
        $search_volume, $average_cpc, $competition, join(", ", @{$categories});
    }
  } else {
    print "No related keywords were found.\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 => "v201710"});

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

# Call the example
get_keyword_ideas($client, $ad_group_id);

Send feedback about...

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