Optimization Samples

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

Estimate keyword traffic

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

require 'adwords_api'

def estimate_keyword_traffic()
  # 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')

  traffic_estimator_srv = adwords.service(:TrafficEstimatorService, API_VERSION)

  # Create keywords. Up to 2000 keywords can be passed in a single request.
  keywords = [
      # The 'xsi_type' field allows you to specify the xsi:type of the object
      # being created. It's only necessary when you must provide an explicit
      # type that the client library can't infer.
    {:xsi_type => 'Keyword', :text => 'mars cruise', :match_type => 'BROAD'},
    {:xsi_type => 'Keyword', :text => 'cheap cruise', :match_type => 'PHRASE'},
    {:xsi_type => 'Keyword', :text => 'cruise', :match_type => 'EXACT'},
    {:xsi_type => 'Keyword', :text => 'moon walk', :match_type => 'BROAD'}
  ]

  # Create a keyword estimate request for each keyword.
  keyword_requests = keywords.map {|keyword| {:keyword => keyword}}

  # Negative keywords don't return estimates, but adjust the estimates of the
  # other keywords in the hypothetical ad group. To specify a negative keyword
  # set the is_negative field to true.
  keyword_requests[3][:is_negative] = true

  # Create ad group estimate requests.
  ad_group_request = {
      :keyword_estimate_requests => keyword_requests,
      :max_cpc => {
          :micro_amount => 1000000
      }
  }

  # Create campaign estimate requests.
  campaign_request = {
      :ad_group_estimate_requests => [ad_group_request],
      # Set targeting criteria. Only locations and languages are supported.
      :criteria => [
          {:xsi_type => 'Location', :id => 2840}, # United States
          {:xsi_type => 'Language', :id => 1000}  # English
      ]
  }

  # Create a selector.
  selector = {
    :campaign_estimate_requests => [campaign_request],
    # Optional: Request a list of campaign level estimates segmented by
    # platform.
    :platform_estimate_requested => true
  }

  # Execute the request.
  response = traffic_estimator_srv.get(selector)

  # Display traffic estimates.
  if response and response[:campaign_estimates] and
      response[:campaign_estimates].size > 0
    campaign_estimate = response[:campaign_estimates].first

    unless campaign_estimate[:platform_estimates].nil?
      # Display the campaign level estimates segmented by platform.
      campaign_estimate[:platform_estimates].each do |platform_estimate|
        platform_message = ('Results for the platform with ID %d and name ' +
            '"%s":') % [platform_estimate[:platform][:id],
            platform_estimate[:platform][:platform_name]]
        display_mean_estimates(
            platform_message,
            platform_estimate[:min_estimate],
            platform_estimate[:max_estimate]
        )
      end
    end

    # Display the keyword estimates.
    keyword_estimates =
        campaign_estimate[:ad_group_estimates].first[:keyword_estimates]
    keyword_estimates.each_with_index do |keyword_estimate, index|
      next if keyword_requests[index][:is_negative]
      keyword = keyword_requests[index][:keyword]

      keyword_message = ('Results for the keyword with text "%s" and match ' +
          'type "%s":') % [keyword[:text], keyword[:match_type]]
      display_mean_estimates(
          keyword_message,
          keyword_estimate[:min],
          keyword_estimate[:max]
      )
    end
  else
    puts 'No traffic estimates were returned.'
  end
end

def display_mean_estimates(message, min_estimate, max_estimate)
  mean_average_cpc = nil
  unless min_estimate[:average_cpc].nil? || max_estimate[:average_cpc].nil?
    mean_average_cpc = calculate_mean(
        min_estimate[:average_cpc][:micro_amount],
        max_estimate[:average_cpc][:micro_amount]
    )
  end
  mean_average_position = calculate_mean(
      min_estimate[:average_position],
      max_estimate[:average_position]
  )
  mean_clicks = calculate_mean(
      min_estimate[:clicks_per_day],
      max_estimate[:clicks_per_day]
  )
  mean_total_cost = nil
  unless min_estimate[:total_cost].nil? || max_estimate[:total_cost].nil?
    mean_total_cost = calculate_mean(
        min_estimate[:total_cost][:micro_amount],
        max_estimate[:total_cost][:micro_amount]
    )
  end

  puts message
  puts "\tEstimated average CPC: %s" % format_mean(mean_average_cpc)
  puts "\tEstimated ad position: %s" % format_mean(mean_average_position)
  puts "\tEstimated daily clicks: %s" % format_mean(mean_clicks)
  puts "\tEstimated daily cost: %s" % format_mean(mean_total_cost)
end

def format_mean(mean)
  return "nil" if mean.nil?
  return "%.2f" % (mean / 1000000)
end

def calculate_mean(min_money, max_money)
  return nil if min_money.nil? || max_money.nil?
  return (min_money.to_f + max_money.to_f) / 2.0
end

if __FILE__ == $0
  API_VERSION = :v201708

  begin
    estimate_keyword_traffic()

  # 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

Get campaign criterion bid modifier simulations

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright:: Copyright 2016, 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 all available campaign criterion bid modifier landscapes
# for a given campaign.
# To get campaigns, run basic_operations/get_campaigns.rb.

require 'adwords_api'

def get_campaign_criterion_bid_modifier_simulations(campaign_id)
  # 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')

  data_srv = adwords.service(:DataService, API_VERSION)

  # Get all the campaigns for this account.
  selector = {
    :fields => [
      'CampaignId',
      'CriterionId',
      'StartDate',
      'EndDate',
      'BidModifier',
      'LocalClicks',
      'LocalCost',
      'LocalImpressions',
      'TotalLocalImpressions',
      'TotalLocalClicks',
      'TotalLocalCost',
      'RequiredBudget'
    ],
    :paging => {
      :start_index => 0,
      :number_results => PAGE_SIZE
    }
  }

  # Set initial values.
  offset, page = 0, {}

  begin
    page = data_srv.get_campaign_criterion_bid_landscape(selector)
    if page[:entries]
      page[:entries].each do |bid_modifier_landscape|
        puts ("Found campaign-level criterion bid modifier landscapes for " +
            "criterion with id '%d', start date '%s', end date '%s', and " +
            "landscape points:") % [
              bid_modifier_landscape[:criterion_id],
              bid_modifier_landscape[:start_date],
              bid_modifier_landscape[:end_date]
            ]
        bid_modifier_landscape[:landscape_points].each do |landscape_point|
          puts ("  bid modifier: %f => clicks: %d, cost: %d, impressions: %d" +
              " total clicks: %d, total cost: %d, total impressions: %d" +
              " and required budget: %f") % [
                landscape_point[:bid_modifier],
                landscape_point[:clicks],
                landscape_point[:cost][:micro_amount],
                landscape_point[:impressions],
                landscape_point[:total_local_clicks],
                landscape_point[:total_local_cost][:micro_amount],
                landscape_point[:total_local_impressions],
                landscape_point[:required_budget][:micro_amount]
              ]
        end
        puts
      end

      # Increment values to request the next page.
      offset += PAGE_SIZE
      selector[:paging][:start_index] = offset
    end
  end while page[:total_num_entries] > offset
end

if __FILE__ == $0
  API_VERSION = :v201708
  PAGE_SIZE = 500

  begin
    campaign_id = 'INSERT_CAMPAIGN_ID_HERE'.to_i

    get_campaign_criterion_bid_modifier_simulations(campaign_id)

  # 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

Get keyword bid simulation

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

require 'adwords_api'

def get_criterion_bid_landscapes(ad_group_id, keyword_id)
  # 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')

  data_srv = adwords.service(:DataService, API_VERSION)

  # Get keyword bid landscape.
  selector = {
    :fields => ['AdGroupId', 'CriterionId', 'StartDate', 'EndDate', 'Bid',
        'LocalClicks', 'LocalCost', 'LocalImpressions'],
    :predicates => [
      {:field => 'AdGroupId', :operator => 'IN', :values => [ad_group_id]},
      {:field => 'CriterionId', :operator => 'IN', :values => [keyword_id]},
    ]
  }
  page = data_srv.get_criterion_bid_landscape(selector)
  if page and page[:entries]
    puts "Bid landscape(s) retrieved: %d." % [page[:entries].length]
    page[:entries].each do |bid_landscape|
      puts ("Retrieved keyword bid landscape with ad group ID %d" +
          ", keyword ID %d, start date '%s', end date '%s'" +
          ", with landscape points:") %
          [bid_landscape[:ad_group_id], bid_landscape[:criterion_id],
           bid_landscape[:start_date], bid_landscape[:end_date]]
      bid_landscape[:landscape_points].each do |point|
        puts "\t%d => clicks: %d, cost: %d, impressions: %d" %
            [point[:bid][:micro_amount], point.clicks,
             point[:cost][:micro_amount], point[:impressions]]
      end
    end
  else
    puts 'No bid landscapes retrieved.'
  end
end

if __FILE__ == $0
  API_VERSION = :v201708

  begin
    ad_group_id = 'INSERT_ADGROUP_ID_HERE'.to_i
    keyword_id = 'INSERT_KEYWORD_ID_HERE'.to_i
    get_criterion_bid_landscapes(ad_group_id, keyword_id)

  # 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

Get keyword ideas

#!/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 retrieves keywords that are related to a given keyword.

require 'adwords_api'

def get_keyword_ideas(keyword_text)
  # 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')

  targeting_idea_srv = adwords.service(:TargetingIdeaService, API_VERSION)

  # Construct selector object.
  selector = {
    :idea_type => 'KEYWORD',
    :request_type => 'IDEAS',
    :requested_attribute_types =>
        ['KEYWORD_TEXT', 'SEARCH_VOLUME', 'CATEGORY_PRODUCTS_AND_SERVICES'],
    :search_parameters => [
      {
        # The 'xsi_type' field allows you to specify the xsi:type of the object
        # being created. It's only necessary when you must provide an explicit
        # type that the client library can't infer.
        :xsi_type => 'RelatedToQuerySearchParameter',
        :queries => [keyword_text]
      },
      {
        # Language setting (optional).
        # The ID can be found in the documentation:
        #  https://developers.google.com/adwords/api/docs/appendix/languagecodes
        # Only one LanguageSearchParameter is allowed per request.
        :xsi_type => 'LanguageSearchParameter',
        :languages => [{:id => 1000}]
      },
      {
        # Network search parameter (optional).
        :xsi_type => 'NetworkSearchParameter',
        :network_setting => {
          :target_google_search => true,
          :target_search_network => false,
          :target_content_network => false,
          :target_partner_search_network => false
        }
      }
    ],
    :paging => {
      :start_index => 0,
      :number_results => PAGE_SIZE
    }
  }

  # Define initial values.
  offset = 0
  results = []

  begin
    # Perform request.
    page = targeting_idea_srv.get(selector)
    results += page[:entries] if page and page[:entries]

    # Prepare next page request.
    offset += PAGE_SIZE
    selector[:paging][:start_index] = offset
  end while offset < page[:total_num_entries]

  # Display results.
  results.each do |result|
    data = result[:data]
    keyword = data['KEYWORD_TEXT'][:value]
    puts "Found keyword with text '%s'" % keyword
    products_and_services = data['CATEGORY_PRODUCTS_AND_SERVICES'][:value]
    if products_and_services
      puts "\tWith Products and Services categories: [%s]" %
          products_and_services.join(', ')
    end
    average_monthly_searches = data['SEARCH_VOLUME'][:value]
    if average_monthly_searches
      puts "\tand average monthly search volume: %d" % average_monthly_searches
    end
  end
  puts "Total keywords related to '%s': %d." % [keyword_text, results.length]
end

if __FILE__ == $0
  API_VERSION = :v201708
  PAGE_SIZE = 100

  begin
    keyword_text = 'INSERT_KEYWORD_TEXT_HERE'
    get_keyword_ideas(keyword_text)

  # 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

Send feedback about...

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