Remarketing Samples

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

Add audience

#!/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 illustrates how to create a user list (a.k.a. Audience) and shows
# its associated conversion tracker code snippet.

require 'adwords_api'

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

  user_list_srv = adwords.service(:AdwordsUserListService, API_VERSION)
  conv_tracker_srv = adwords.service(:ConversionTrackerService, API_VERSION)

  # Prepare for adding remarketing user list.
  name = "Mars cruise customers #%d" % (Time.new.to_f * 1000).to_i
  operation = {
    :operator => 'ADD',
    :operand => {
      # 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 => 'BasicUserList',
      :name => name,
      :description => 'A list of mars cruise customers in the last year',
      :membership_life_span => 365,
      :conversion_types => [{:name => name}],
      # Optional field.
      :status => 'OPEN'
    }
  }

  # Add user list.
  response = user_list_srv.mutate([operation])
  if response and response[:value]
    user_list = response[:value].first

    # Get conversion snippets.
    if user_list and user_list[:conversion_types]
      conversion_ids = user_list[:conversion_types][:id]
      selector = {
        # We're actually interested in the 'Snippet' field, which is returned
        # automatically.
        :fields => ['Id'],
        :predicates => [
          {:field => 'Id', :operator => 'IN', :values => [conversion_ids]}
        ]
      }
      conv_tracker_response = conv_tracker_srv.get(selector)
      if conv_tracker_response and conv_tracker_response[:entries]
        conversions = conv_tracker_response[:entries]
      end
    end
    puts "User list with name '%s' and ID %d was added." %
        [user_list[:name], user_list[:id]]
    # Display user list associated conversion code snippets.
    if conversions
      conversions.each do |conversion|
        puts "Conversion type code snipped associated to the list:\n\t\t%s\n" %
          conversion[:snippet]
      end
    end
  else
    puts 'No user lists were added.'
  end
end

if __FILE__ == $0
  API_VERSION = :v201705

  begin
    add_audience()

  # 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

Add conversion tracker

#!/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 illustrates how to add an AdWords conversion tracker.

require 'adwords_api'

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

  conv_tracker_srv = adwords.service(:ConversionTrackerService, API_VERSION)

  # Prepare for adding conversion.
  operation = {
    :operator => 'ADD',
    :operand => {
      # 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 => 'AdWordsConversionTracker',
      :name => "Earth to Mars Cruises Conversion #%d" %
          (Time.new.to_f * 1000).to_i,
      :category => 'DEFAULT',
      :text_format => 'HIDDEN',
      # Optional fields:
      :status => 'ENABLED',
      :viewthrough_lookback_window => 15,
      :conversion_page_language => 'en',
      :background_color => '#0000FF',
      :default_revenue_value => 23.41,
      :always_use_default_revenue_value => true
    }
  }

  # Add conversion.
  response = conv_tracker_srv.mutate([operation])
  if response and response[:value]
    conversion = response[:value].first
    puts ("Conversion with ID %d, name '%s', status '%s' and category '%s'" +
        " was added.") % [conversion[:id], conversion[:name],
        conversion[:status], conversion[:category]]
  else
    puts 'No conversions were added.'
  end
end

if __FILE__ == $0
  API_VERSION = :v201705

  begin
    add_conversion_tracker()

  # 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

Add CRM-based user list

#!/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 adds a user list (a.k.a. audience) and uploads members to
# populate the list.
#
# Note: It may take several hours for the list to be populated with members.
# Email addresses and other member information must be associated with a Google
# account. For privacy purposes, the user list size will show as zero until the
# list has at least 1000 members. After that, the size will be rounded to the
# two most significant digits.

require 'adwords_api'
require 'digest'

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

  user_list_srv = adwords.service(:AdwordsUserListService, API_VERSION)

  user_list = {
    :xsi_type => 'CrmBasedUserList',
    :name => 'Customer relationship management list #%d' % Time.new.usec,
    :description => 'A list of customers that originated from email addresses',
    # Maximum life span is 180 days.
    :membership_life_span => 180
  }

  operation = {
    :operand => user_list,
    :operator => 'ADD'
  }

  result = user_list_srv.mutate([operation])
  user_list_id = result[:value].first[:id]

  emails = ['customer1@example.com', 'customer2@example.com',
      ' Customer3@example.com ']

  sha_digest = Digest::SHA256.new
  members = emails.map do |email|
    # Remove leading and trailing whitespace and convert all characters to
    # lowercase before generating the hashed version.
    {
      :hashed_email => sha_digest.hexdigest(normalize_text(email))
    }
  end

  # Adding address info is currently available on a whitelist-only basis. This
  # code demonstrates how to do it, and you can uncomment it if you are on the
  # whitelist.
  # first_name = 'John'
  # last_name = 'Doe'
  # country_code = 'US'
  # zip_code = '10001'
  #
  # members << {
  #   :address_info => {
  #     # First and last name must be normalized and hashed.
  #     :hashed_first_name => sha_digest.hexdigest(normalize_text(first_name)),
  #     :hashed_last_name => sha_digest.hexdigest(normalize_text(last_name)),
  #     # Country code and zip code are sent in plaintext.
  #     :country_code => country_code,
  #     :zip_code => zip_code
  #   }
  # }

  mutate_members_operation = {
    :operand => {
      :user_list_id => user_list_id,
      :members_list => members
    },
    :operator => 'ADD'
  }

  mutate_members_result =
      user_list_srv.mutate_members([mutate_members_operation])

  mutate_members_result[:user_lists].each do |user_list|
    puts "User list with name '%s' and ID '%d' was added." %
        [user_list[:name], user_list[:id]]
  end
end

def normalize_text(text)
  text.strip.downcase
end

if __FILE__ == $0
  API_VERSION = :v201705

  begin
    add_crm_based_user_list()

  # 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

Add rule-based user list

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright:: Copyright 2014, 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 adds two rule-based remarketing user lists: one with no site
# visit data restrictions, and another that will only include users who visit
# your site in the next six months.

require 'adwords_api'

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

  user_list_srv = adwords.service(:AdwordsUserListService, API_VERSION)

  # First rule item group - users who visited the checkout page and had more
  # than one item in their shopping cart.
  cart_rule_item = {
    :xsi_type => 'StringRuleItem',
    :key => {
      :name => 'ecomm_pagetype'
    },
    :op => 'EQUALS',
    :value => 'checkout'
  }

  cart_size_rule_item = {
    :xsi_type => 'NumberRuleItem',
    :key => {
      :name => 'cartsize'
    },
    :op => 'GREATER_THAN',
    :value => 1.0
  }

  # Combine the two rule items into a RuleItemGroup so AdWords will AND
  # their rules together.
  checkout_multiple_item_group = {
    :items => [cart_rule_item, cart_size_rule_item]
  }

  # Second rule item group - users who checked out after October 31st
  # and before January 1st.
  start_date_rule_item = {
    :xsi_type => 'DateRuleItem',
    :key => {
      :name => 'checkoutdate'
    },
    :op => 'AFTER',
    :value => '20141031'
  }

  end_date_rule_item = {
    :xsi_type => 'DateRuleItem',
    :key => {
      :name => 'checkoutdate'
    },
    :op => 'BEFORE',
    :value => '20150101'
  }

  # Combine the date rule items into a RuleItemGroup.
  checked_out_nov_dec_item_group = {
    :items => [start_date_rule_item, end_date_rule_item]
  }

  # Combine the rule item groups into a Rule so AdWords knows how to apply the
  # rules.
  rule = {
    :groups => [checkout_multiple_item_group, checked_out_nov_dec_item_group],
    # ExpressionRuleUserLists can use either CNF or DNF for matching. CNF means
    # 'at least one item in each rule item group must match', and DNF means 'at
    # least one entire rule item group must match'.
    # DateSpecificRuleUserList only supports DNF. You can also omit the rule
    # type altogether to default to DNF.
    :rule_type => 'DNF'
  }

  # Create the user list with no restrictions on site visit date.
  expression_user_list = {
    :xsi_type => 'ExpressionRuleUserList',
    :name => 'Users who checked out in November or December OR ' +
        'visited the checkout page with more than one item in their cart',
    :description => 'Expression based user list',
    :rule => rule,
    # Optional: Set the prepopulationStatus to REQUESTED to include past users
    # in the user list.
    :prepopulation_status => 'REQUESTED'
  }

  # Create the user list restricted to users who visit your site within the
  # specified timeframe.
  date_user_list = {
    :xsi_type => 'DateSpecificRuleUserList',
    :name => 'Date rule user list created at ' + Time.now.to_s,
    :description => 'Users who visited the site between 20141031 and ' +
        '20150331 and checked out in November or December OR visited the ' +
        'checkout page with more than one item in their cart',
    # We re-use the rule here. To avoid side effects, we need a deep copy.
    :rule => Marshal.load(Marshal.dump(rule)),
    # Set the start and end dates of the user list.
    :start_date => '20141031',
    :end_date => '20150331'
  }

  # Create operations to add the user lists.
  operations = [expression_user_list, date_user_list].map do |user_list|
    {
      :operand => user_list,
      :operator => 'ADD'
    }
  end

  # Submit the operations.
  response = user_list_srv.mutate(operations)

  # Display the results.
  response[:value].each do |user_list|
    puts ("User list added with ID %d, name '%s', status '%s', " +
        "list type '%s', accountUserListStatus '%s', description '%s'.") %
        [user_list[:id], user_list[:name], user_list[:status],
        user_list[:list_type], user_list[:account_user_list_status],
        user_list[:description]]
  end
end

if __FILE__ == $0
  API_VERSION = :v201705

  begin
    add_rule_based_user_lists()

  # 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

Upload offline conversions

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright:: Copyright 2013, 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 code example imports offline conversion values for specific clicks to
# your account. To get Google Click ID for a click, run
# CLICK_PERFORMANCE_REPORT. To set up a conversion tracker, run the
# add_conversion_tracker.rb example.

require 'adwords_api'
require 'date'

def upload_offline_conversions(conversion_name, google_click_id,
                               conversion_time, conversion_value)
  # 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')

  conversion_feed_srv =
      adwords.service(:OfflineConversionFeedService, API_VERSION)

  # Associate offline conversions with the existing named conversion tracker. If
  # this tracker was newly created, it may be a few hours before it can accept
  # conversions.
  feed = {
    :conversion_name => conversion_name,
    :google_click_id => google_click_id,
    :conversion_time => conversion_time,
    :conversion_value => conversion_value
  }
  return_feeds = conversion_feed_srv.mutate([
    {:operator => 'ADD', :operand => feed}])
  return_feeds[:value].each do |return_feed|
    puts ("Uploaded offline conversion value %.2f for Google Click ID '%s', " +
        'to %s') % [return_feed[:conversion_value],
                    return_feed[:google_click_id],
                    return_feed[:conversion_name]]
  end
end

if __FILE__ == $0
  API_VERSION = :v201705

  begin
    # Name of the conversion tracker to upload to.
    conversion_name = 'INSERT_CONVERSION_NAME_HERE'
    # Google Click ID of the click for which offline conversions are uploaded.
    google_click_id = 'INSERT_GOOGLE_CLICK_ID_HERE'
    # Conversion time in 'yyyymmdd hhmmss' format.
    conversion_time = Time.new.strftime("%Y%m%d %H%M%S")
    # Conversion value to be uploaded.
    conversion_value = 'INSERT_CONVERSION_VALUE_HERE'.to_f

    upload_offline_conversions(conversion_name, google_click_id,
                               conversion_time, conversion_value)

  # 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

Upload offline call conversions

#!/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 code example imports offline conversion values for calls related to ads
# in your account.
#
# To set up a conversion tracker, run the add_conversion_tracker.rb example.

require 'adwords_api'

def upload_offline_call_conversions(caller_id, call_start_time, conversion_name,
    conversion_time, conversion_value)
  # 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')

  occ_feed_srv =
      adwords.service(:OfflineCallConversionFeedService, API_VERSION)

  # Associate offline conversions with the existing named conversion tracker. If
  # this tracker was newly created, it may be a few hours before it can accept
  # conversions.
  feed = {
    :caller_id => caller_id,
    :call_start_time => call_start_time,
    :conversion_name => conversion_name,
    :conversion_time => conversion_time,
    :conversion_value => conversion_value
  }

  occ_operations = [{
    :operator => 'ADD',
    :operand => feed
  }]

  occ_response = occ_feed_srv.mutate(occ_operations)

  if occ_response[:value]
    occ_response[:value].each do |occ_feed|
      puts 'Uploaded offline call conversion value "%s" for caller ID "%s"' %
          [occ_feed[:conversion_name], occ_feed[:caller_id]]
    end
  end
end

if __FILE__ == $0
  API_VERSION = :v201705

  begin
    caller_id = 'INSERT_CALLER_ID_HERE'
    # For times, use the format yyyyMMdd HHmmss tz. For more details on
    # formats, see:
    # https://developers.google.com/adwords/api/docs/appendix/codes-formats#date-and-time-formats
    # For time zones, see:
    # https://developers.google.com/adwords/api/docs/appendix/codes-formats#timezone-ids
    call_start_time = 'INSERT_CALL_START_TIME_HERE'
    conversion_name = 'INSERT_CONVERSION_NAME_HERE'
    conversion_time = 'INSERT_CONVERSION_TIME_HERE'
    conversion_value = 'INSERT_CONVERSION_VALUE_HERE'

    upload_offline_call_conversions(
        caller_id,
        call_start_time,
        conversion_name,
        conversion_time,
        conversion_value
    )

  # 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.