Advanced Operations Samples

The code samples below provide examples of common advanced operations using the AdWords API. Client Library.

Add an ad customizer

#!/usr/bin/env python
#
# Copyright 2016 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.

"""Adds an ad customizer feed.

Associates the feed with customer and adds an ad that uses the feed to populate
dynamic data.

"""


from datetime import datetime
from uuid import uuid4

# Import appropriate classes from the client library.
from googleads import adwords
from googleads import errors


FEED_NAME = 'Interplanetary Feed Name %s' % uuid4()
ADGROUPS = [
    'INSERT_ADGROUP_ID_1_HERE',
    'INSERT_ADGROUP_ID_2_HERE'
]


def CreateAdsWithCustomizations(client, adgroup_ids, feed_name):
  """Creates ExpandedTextAds that use ad customizations for specified AdGroups.

  Args:
    client: an AdWordsClient instance.
    adgroup_ids: a list containing the AdGroup ids to add ExpandedTextAds to.
    feed_name: the name of the feed used to apply customizations.

  Raises:
    GoogleAdsError: if no ExpandedTextAds were added.
  """
  # Get the AdGroupAdService
  adgroup_ad_service = client.GetService('AdGroupAdService', 'v201710')

  expanded_text_ad = {
      'xsi_type': 'ExpandedTextAd',
      'headlinePart1': 'Luxury Cruise to {=%s.Name}' % feed_name,
      'headlinePart2': 'Only {=%s.Price}' % feed_name,
      'description': 'Offer ends in {=countdown(%s.Date)}!' % feed_name,
      'finalUrls': ['http://www.example.com'],
  }

  # We add the same ad to both ad groups. When they serve, they will show
  # different values, since they match different feed items.
  operations = [{
      'operator': 'ADD',
      'operand': {
          'adGroupId': adgroup,
          'ad': expanded_text_ad
      }
  } for adgroup in adgroup_ids]

  response = adgroup_ad_service.mutate(operations)

  if response and 'value' in response:
    for ad in response['value']:
      print ('Created an ad with ID "%s", type "%s", and status "%s".'
             % (ad['ad']['id'], ad['ad']['Ad.Type'], ad['status']))
  else:
    raise errors.GoogleAdsError('No ads were added.')


def CreateCustomizerFeed(client, feed_name):
  """Creates a new AdCustomizerFeed.

  Args:
    client: an AdWordsClient instance.
    feed_name: the name for the new AdCustomizerFeed.

  Returns:
    The new AdCustomizerFeed.
  """
  # Get the AdCustomizerFeedService
  ad_customizer_feed_service = client.GetService('AdCustomizerFeedService',
                                                 'v201710')
  customizer_feed = {
      'feedName': feed_name,
      'feedAttributes': [
          {'type': 'STRING', 'name': 'Name'},
          {'type': 'STRING', 'name': 'Price'},
          {'type': 'DATE_TIME', 'name': 'Date'}
      ]
  }

  feed_service_operation = {
      'operator': 'ADD',
      'operand': customizer_feed
  }

  response = ad_customizer_feed_service.mutate([feed_service_operation])

  if response and 'value' in response:
    feed = response['value'][0]
    feed_data = {
        'feedId': feed['feedId'],
        'nameId': feed['feedAttributes'][0]['id'],
        'priceId': feed['feedAttributes'][1]['id'],
        'dateId': feed['feedAttributes'][2]['id']
    }
    print ('Feed with name "%s" and ID %s was added with:\n'
           '\tName attribute ID %s and price attribute ID %s and date attribute'
           'ID %s') % (feed['feedName'], feed['feedId'], feed_data['nameId'],
                       feed_data['priceId'], feed_data['dateId'])
    return feed
  else:
    raise errors.GoogleAdsError('No feeds were added')


def CreateCustomizerFeedItems(client, adgroup_ids, ad_customizer_feed):
  """Creates FeedItems for the specified AdGroups.

  These FeedItems contain values to use in ad customizations for the AdGroups.

  Args:
    client: an AdWordsClient instance.
    adgroup_ids: a list containing two AdGroup Ids.
    ad_customizer_feed: the AdCustomizerFeed we're associating the FeedItems
        with.

  Raises:
    GoogleAdsError: if no FeedItems were added.
  """
  # Get the FeedItemService
  feed_item_service = client.GetService('FeedItemService', 'v201710')
  now = datetime.now()
  mars_date = datetime(now.year, now.month, 1, 0, 0)
  venus_date = datetime(now.year, now.month, 15, 0, 0)
  time_format = '%Y%m%d %H%M%S'

  feed_item_operations = [
      CreateFeedItemAddOperation(
          'Mars', '$1234.56', mars_date.strftime(time_format), adgroup_ids[0],
          ad_customizer_feed),
      CreateFeedItemAddOperation(
          'Venus', '$1450.00', venus_date.strftime(time_format),
          adgroup_ids[1], ad_customizer_feed)
  ]

  response = feed_item_service.mutate(feed_item_operations)

  if 'value' in response:
    for feed_item in response['value']:
      print 'Added FeedItem with ID %d.' % feed_item['feedItemId']
  else:
    raise errors.GoogleAdsError('No FeedItems were added.')


def CreateFeedItemAddOperation(name, price, date, adgroup_id,
                               ad_customizer_feed):
  """Creates a FeedItemOperation.

  The generated FeedItemOperation will create a FeedItem with the specified
  values and AdGroupTargeting when sent to FeedItemService.mutate.

  Args:
    name: the value for the name attribute of the FeedItem.
    price: the value for the price attribute of the FeedItem.
    date: the value for the date attribute of the FeedItem.
    adgroup_id: the ID of the ad_group to target with the FeedItem.
    ad_customizer_feed: the AdCustomizerFeed we're associating the FeedItems
        with.

  Returns:
    A new FeedItemOperation for adding a FeedItem.
  """
  feed_item = {
      'feedId': ad_customizer_feed['feedId'],
      'adGroupTargeting': {
          'TargetingAdGroupId': adgroup_id
      },
      'attributeValues': [
          {
              'feedAttributeId': ad_customizer_feed['feedAttributes'][0]['id'],
              'stringValue': name
          },
          {
              'feedAttributeId': ad_customizer_feed['feedAttributes'][1]['id'],
              'stringValue': price
          },
          {
              'feedAttributeId': ad_customizer_feed['feedAttributes'][2]['id'],
              'stringValue': date
          }
      ]
  }

  operation = {
      'operator': 'ADD',
      'operand': feed_item
  }

  return operation


def main(client, adgroup_ids, feed_name=FEED_NAME):
  # Create a customizer feed. One feed per account can be used for all ads.
  ad_customizer_feed = CreateCustomizerFeed(client, feed_name)
  # Add feed items containing the values we'd like to place in ads.
  CreateCustomizerFeedItems(client, adgroup_ids, ad_customizer_feed)
  # All set! We can now create ads with customizations.
  CreateAdsWithCustomizations(client, adgroup_ids, feed_name)


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()
  main(adwords_client, ADGROUPS)

Add an ad group bid modifier

#!/usr/bin/env python
#
# Copyright 2016 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.

"""Adds an ad group level mobile bid modifier override for a campaign.

To get your ad groups, run get_ad_groups.py.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""

from googleads import adwords


AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE'
BID_MODIFIER = 'INSERT_BID_MODIFIER_HERE'


def main(client, ad_group_id, bid_modifier):
  # Initialize appropriate service.
  ad_group_bid_modifier_service = client.GetService(
      'AdGroupBidModifierService', version='v201710')

  # Mobile criterion ID.
  criterion_id = '30001'

  # Prepare to add an ad group level override.
  operation = {
      # Use 'ADD' to add a new modifier and 'SET' to update an existing one. A
      # modifier can be removed with the 'REMOVE' operator.
      'operator': 'ADD',
      'operand': {
          'adGroupId': ad_group_id,
          'criterion': {
              'xsi_type': 'Platform',
              'id': criterion_id
          },
          'bidModifier': bid_modifier
      }
  }

  # Add ad group level mobile bid modifier.
  response = ad_group_bid_modifier_service.mutate([operation])
  if response and response['value']:
    modifier = response['value'][0]
    value = modifier['bidModifier'] if 'bidModifier' in modifier else 'unset'
    print ('Campaign ID %s, AdGroup ID %s, Criterion ID %s was updated with '
           'ad group level modifier: %s' %
           (modifier['campaignId'], modifier['adGroupId'],
            modifier['criterion']['id'], value))
  else:
    print 'No modifiers were added.'


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client, AD_GROUP_ID, BID_MODIFIER)

Add a click-to-download ad

#!/usr/bin/env python
#
# Copyright 2016 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 creates a click-to-download ad in a given ad group.

This type of ad is also known as an app promotion ad. To list ad groups, run
get_ad_groups.py.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""

import base64
import urllib2

from googleads import adwords


AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE'


def main(client, ad_group_id):
  # Initialize appropriate service.
  ad_group_ad_service = client.GetService('AdGroupAdService', version='v201710')

  # Optionally, you may specify a landscape image. The image needs to be in a
  # BASE64 encoded form. Here we download a demo image and encode it for this
  # ad.
  opener = urllib2.build_opener(*client.proxy_config.GetHandlers())
  # Note: The utf-8 decode is for 2to3 Python 3 compatibility.
  image_data = (base64.b64encode(opener.open('http://goo.gl/9JmyKk').read())
                .decode('utf-8'))

  # Create the template elements for the ad. You can refer to
  #     https://developers.google.com/adwords/api/docs/appendix/templateads
  # for the list of available template fields.
  ad_data = {
      'uniqueName': 'adData',
      'fields': [
          {
              'name': 'headline',
              'fieldText': 'Enjoy your drive in Mars',
              'type': 'TEXT'
          },
          {
              'name': 'description1',
              'fieldText': 'Realistic physics simulation',
              'type': 'TEXT'
          },
          {
              'name': 'description2',
              'fieldText': 'Race against players online',
              'type': 'TEXT'
          },
          {
              'name': 'appId',
              'fieldText': 'com.example.demogame',
              'type': 'TEXT'
          },
          {
              'name': 'appStore',
              'fieldText': '2',
              'type': 'ENUM'
          },
          {
              'name': 'landscapeImage',
              'fieldMedia': {
                  'xsi_type': 'Image',
                  'data': image_data
              },
              'type': 'IMAGE'
          }
      ]
  }

  # Create click to download ad.
  click_to_download_app_ad = {
      'xsi_type': 'TemplateAd',
      'name': 'Ad for demo game',
      'templateId': '353',
      'finalUrls': [
          'http://play.google.com/store/apps/details?id=com.example.demogame'
      ],
      'displayUrl': 'play.google.com',
      'templateElements': [ad_data]
  }

  # Create ad group ad.
  ad_group_ad = {
      'adGroupId': ad_group_id,
      'ad': click_to_download_app_ad,
      # Optional.
      'status': 'PAUSED'
  }

  # Add ad.
  ads = ad_group_ad_service.mutate([
      {'operator': 'ADD', 'operand': ad_group_ad}
  ])
  # Display results.
  if 'value' in ads:
    for ad in ads['value']:
      print ('Added new click-to-download ad with ID "%s" and final URL "%s".'
             % (ad['ad']['id'], ad['ad']['finalUrls'][0]))
  else:
    print 'No ads were added.'


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()
  main(adwords_client, AD_GROUP_ID)

Add a page feed specifying URLs for a DSA campaign

#!/usr/bin/env python
#
# Copyright 2016 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.

"""Adds page feed to specify URLs to use with your Dynamic Search Ads campaign.

To create a Dynamic Search Ads campaign, run add_dynamic_search_ad_campaign.py.
To get campaigns, run get_campaigns.py.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.
"""

from collections import namedtuple
import uuid

from googleads import adwords


AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE'
CAMPAIGN_ID = 'INSERT_CAMPAIGN_ID_HERE'

# Used to keep track of DSA page feed details.
_DSAFeedDetails = namedtuple(
    '_DSAFeedDetails', ['feed_id', 'url_attribute_id', 'label_attribute_id'])
# ID that corresponds to the labels.
DSA_LABEL_FIELD_ID = 2
# The criterion type to be used for DSA page feeds.
DSA_PAGE_FEED_CRITERION_TYPE = 61
DSA_PAGE_URL_LABEL = 'discounts'
# ID that corresponds to the page URLs.
DSA_PAGE_URLS_FIELD_ID = 1


def main(client, campaign_id, ad_group_id):
  # Get the page feed details. This code example creates a new feed, but you can
  # fetch and re-use an existing feed.
  feed_details = _CreateFeed(client)
  _CreateFeedMapping(client, feed_details)
  _CreateFeedItems(client, feed_details, DSA_PAGE_URL_LABEL)

  # Associate the page feed with the campaign.
  _UpdateCampaignDSASetting(client, campaign_id, feed_details.feed_id)

  # Optional: Target web pages matching the feed's label in the ad group.
  _AddDSATargeting(client, ad_group_id, DSA_PAGE_URL_LABEL)

  print 'Dynamic page feed setup complete for campaign ID "%d".' % campaign_id


def _CreateFeed(client):
  """Creates the feed for DSA page URLs.

  Args:
    client: an AdWordsClient instance.

  Returns:
    A _DSAFeedDetails instance containing details about the created feed.
  """
  # Get the FeedService.
  feed_service = client.GetService('FeedService', version='v201710')

  # Create operation.
  operation = {
      # Create the feed.
      'operand': {
          'name': 'DSA Feed %s' % uuid.uuid4(),
          # Create attributes.
          'attributes': [
              {'type': 'URL_LIST', 'name': 'Page URL'},
              {'type': 'STRING_LIST', 'name': 'Label'}
          ],
          'origin': 'USER'
      },
      'operator': 'ADD'
  }

  # Add the feed.
  feed = feed_service.mutate([operation])['value'][0]
  return _DSAFeedDetails(feed['id'], feed['attributes'][0]['id'],
                         feed['attributes'][1]['id'])


def _CreateFeedMapping(client, feed_details):
  """Creates the feed mapping for DSA page feeds.

  Args:
    client: an AdWordsClient instance.
    feed_details: a _DSAFeedDetails instance.
  """
  # Get the FeedMappingService.
  feed_mapping_service = client.GetService('FeedMappingService',
                                           version='v201710')

  # Create the operation.
  operation = {
      # Create the feed mapping.
      'operand': {
          'criterionType': DSA_PAGE_FEED_CRITERION_TYPE,
          'feedId': feed_details.feed_id,
          # Map the feedAttributeIds to the fieldId constants.
          'attributeFieldMappings': [
              {
                  'feedAttributeId': feed_details.url_attribute_id,
                  'fieldId': DSA_PAGE_URLS_FIELD_ID
              },
              {
                  'feedAttributeId': feed_details.label_attribute_id,
                  'fieldId': DSA_LABEL_FIELD_ID
              }
          ]
      },
      'operator': 'ADD'
  }

  # Add the feed mapping.
  feed_mapping_service.mutate([operation])


def _CreateFeedItems(client, feed_details, label_name):
  """Creates the page URLs in the DSA page feed.

  Args:
    client: an AdWordsClient instance.
    feed_details: a _DSAFeedDetails instance.
    label_name: a str containing the page feed URL label.
  """
  # Get the FeedItemService.
  feed_item_service = client.GetService('FeedItemService', version='v201710')

  # Optional: You can include the {feeditem} valuetrack parameter to track which
  # page feed items lead to each click.
  urls = ('http://www.example.com/discounts/rental-cars?id={feeditem}',
          'http://www.example.com/discounts/hotel-deals?id={feeditem}',
          'http://www.example.com/discounts/flight-deals?id={feeditem}')

  # Create the operation.
  operations = [{
      # Create the feed item.
      'operand': {
          'feedId': feed_details.feed_id,
          'attributeValues': [
              {
                  'feedAttributeId': feed_details.url_attribute_id,
                  'stringValues': [url]
              },
              {
                  'feedAttributeId': feed_details.label_attribute_id,
                  'stringValues': [label_name]
              }
          ]
      },
      'operator': 'ADD'
  } for url in urls]

  # Add the feed item.
  feed_item_service.mutate(operations)


def _UpdateCampaignDSASetting(client, campaign_id, feed_id):
  """Updates the campaign DSA setting to DSA pagefeeds.

  Args:
    client: an AdWordsClient instance.
    campaign_id: a str Campaign ID.
    feed_id: a str page Feed ID.

  Raises:
    ValueError: If the given campaign is found not to be a dynamic search ad
    campaign.
  """
  # Get the CampaignService.
  campaign_service = client.GetService('CampaignService', version='v201710')

  selector = {
      'fields': ['Id', 'Settings'],
      'predicates': [{
          'field': 'Id',
          'operator': 'EQUALS',
          'values': [campaign_id]
      }]
  }

  response = campaign_service.get(selector)

  if response['totalNumEntries']:
    campaign = response['entries'][0]
  else:
    raise ValueError('No campaign with ID "%d" exists.' % campaign_id)

  if not campaign['settings']:
    raise ValueError('This is not a DSA campaign.')

  dsa_setting = None

  campaign_settings = campaign['settings']

  for setting in campaign_settings:
    if setting['Setting.Type'] == 'DynamicSearchAdsSetting':
      dsa_setting = setting
      break

  if dsa_setting is None:
    raise ValueError('This is not a DSA campaign.')

  dsa_setting['pageFeed'] = {
      'feedIds': [feed_id]
  }

  # Optional: Specify whether only the supplied URLs should be used with your
  # Dynamic Search Ads.
  dsa_setting['useSuppliedUrlsOnly'] = True

  operation = {
      'operand': {
          'id': campaign_id,
          'settings': campaign_settings
      },
      'operator': 'SET'
  }

  campaign_service.mutate([operation])
  print 'DSA page feed for campaign ID "%d" was updated with feed ID "%d".' % (
      campaign_id, feed_id)


def _AddDSATargeting(client, ad_group_id, label_name):
  """Set custom targeting for the page feed URLs based on a list of labels.

  Args:
    client: an AdWordsClient instance.
    ad_group_id: a str AdGroup ID.
    label_name: a str label name.

  Returns:
    A suds.sudsobject.Object representing the newly created webpage criterion.
  """
  # Get the AdGroupCriterionService.
  ad_group_criterion_service = client.GetService('AdGroupCriterionService',
                                                 version='v201710')

  # Create the operation.
  operation = {
      'operand': {
          'xsi_type': 'BiddableAdGroupCriterion',
          'adGroupId': ad_group_id,
          # Create a webpage criterion.
          'criterion': {
              'xsi_type': 'Webpage',
              'parameter': {
                  'criterionName': 'Test criterion',
                  # Add a condition for label=specified_label_name.
                  'conditions': [{
                      'operand': 'CUSTOM_LABEL',
                      'argument': label_name
                  }],
              }
          },
          # Set a custom bid for this criterion
          'biddingStrategyConfiguration': {
              'bids': [{
                  'xsi_type': 'CpcBid',
                  'bid': {
                      'microAmount': 1500000
                  }
              }]
          }
      },
      'operator': 'ADD'
  }

  criterion = ad_group_criterion_service.mutate([operation])['value'][0]
  print 'Web page criterion with ID "%d" and status "%s" was created.' % (
      criterion['criterion']['id'], criterion['userStatus'])
  return criterion


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()
  main(adwords_client, CAMPAIGN_ID, AD_GROUP_ID)

Add a DSA campaign

#!/usr/bin/env python
#
# Copyright 2016 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 adds a Dynamic Search Ads campaign.

To get campaigns, run get_campaigns.py.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.
"""


import datetime
import uuid
from googleads import adwords


def main(client):
  budget = _CreateBudget(client)
  campaign_id = _CreateCampaign(client, budget)
  ad_group_id = _CreateAdGroup(client, campaign_id)
  _CreateExpandedDSA(client, ad_group_id)
  _AddWebPageCriteria(client, ad_group_id)

  print 'Dynamic Search Ads campaign setup is complete.'


def _CreateBudget(client):
  """Creates the budget.

  Args:
    client: an AdWordsClient instance.

  Returns:
    a suds.sudsobject.Object representation of the created budget.
  """
  budget_service = client.GetService('BudgetService', version='v201710')

  # Create the campaign budget
  operation = {
      'operand': {
          'name': 'Interplanetary Cruise Budget #%d' % uuid.uuid4(),
          'deliveryMethod': 'STANDARD',
          'amount': {
              'microAmount': 500000
          }
      },
      'operator': 'ADD'
  }

  budget = budget_service.mutate([operation])['value'][0]

  print 'Budget with ID "%d" and name "%s" was created.' % (
      budget['budgetId'], budget['name'])

  return budget


def _CreateCampaign(client, budget):
  """Creates the campaign.

  Args:
    client: an AdWordsClient instance.
    budget: a suds.sudsobject.Object representation of a created budget.

  Returns:
    An integer campaign ID.
  """
  campaign_service = client.GetService('CampaignService')

  operations = [{
      'operator': 'ADD',
      'operand': {
          'name': 'Interplanetary Cruise #%d' % uuid.uuid4(),
          # Recommendation: Set the campaign to PAUSED when creating it to
          # prevent the ads from immediately serving. Set to ENABLED once you've
          # added targeting and the ads are ready to serve.
          'status': 'PAUSED',
          'advertisingChannelType': 'SEARCH',
          'biddingStrategyConfiguration': {
              'biddingStrategyType': 'MANUAL_CPC',
          },
          'budget': budget,
          # Required: Set the campaign's Dynamic Search Ad settings.
          'settings': [{
              'xsi_type': 'DynamicSearchAdsSetting',
              # Required: Set the domain name and language.
              'domainName': 'example.com',
              'languageCode': 'en'
          }],
          # Optional: Set the start date.
          'startDate': (datetime.datetime.now() +
                        datetime.timedelta(1)).strftime('%Y%m%d'),
          # Optional: Set the end date.
          'endDate': (datetime.datetime.now() +
                      datetime.timedelta(365)).strftime('%Y%m%d'),
      }
  }]

  campaign = campaign_service.mutate(operations)['value'][0]
  campaign_id = campaign['id']

  print 'Campaign with ID "%d" and name "%s" was added.' % (
      campaign_id, campaign['name'])

  return campaign_id


def _CreateAdGroup(client, campaign_id):
  """Creates an ad group.

  Args:
    client: an AdWordsClient instance.
    campaign_id: an integer campaign ID.

  Returns:
    An integer ad group ID.
  """
  ad_group_service = client.GetService('AdGroupService')

  operations = [{
      'operator': 'ADD',
      'operand': {
          'campaignId': campaign_id,
          'adGroupType': 'SEARCH_DYNAMIC_ADS',
          'name': 'Earth to Mars Cruises #%d' % uuid.uuid4(),
          'status': 'PAUSED',
          'biddingStrategyConfiguration': {
              'bids': [{
                  'xsi_type': 'CpcBid',
                  'bid': {
                      'microAmount': '3000000'
                  },
              }]
          }
      }
  }]

  ad_group = ad_group_service.mutate(operations)['value'][0]
  ad_group_id = ad_group['id']

  print 'Ad group with ID "%d" and name "%s" was created.' % (
      ad_group_id, ad_group['name'])

  return ad_group_id


def _CreateExpandedDSA(client, ad_group_id):
  """Creates the expanded Dynamic Search Ad.

  Args:
    client: an AdwordsClient instance.
    ad_group_id: an integer ID of the ad group in which the DSA is added.
  """
  # Get the AdGroupAdService.
  ad_group_ad_service = client.GetService('AdGroupAdService')

  # Create the operation
  operations = [{
      'operator': 'ADD',
      'operand': {
          'xsi_type': 'AdGroupAd',
          'adGroupId': ad_group_id,
          # Create the expanded dynamic search ad. This ad will have its
          # headline and final URL auto-generated at serving time according to
          # domain name specific information provided by DynamicSearchAdsSetting
          # at the campaign level.
          'ad': {
              'xsi_type': 'ExpandedDynamicSearchAd',
              # Set the ad description.
              'description': 'Buy your tickets now!'
          },
          # Optional: Set the status.
          'status': 'PAUSED',
      }
  }]

  # Create the ad.
  ad = ad_group_ad_service.mutate(operations)['value'][0]['ad']

  # Display the results.
  print ('Expanded dynamic search ad with ID "%d" and description "%s" was '
         'added' % (ad['id'], ad['description']))


def _AddWebPageCriteria(client, ad_group_id):
  """Adds a web page criterion to target Dynamic Search Ads.

  Args:
    client: an AdWordsClient instance.
    ad_group_id: an integer ID of the ad group the criteria is being added to.
  """
  ad_group_criterion_service = client.GetService('AdGroupCriterionService',
                                                 version='v201710')

  operations = [{
      'operator': 'ADD',
      # Create biddable ad group criterion.
      'operand': {
          'xsi_type': 'BiddableAdGroupCriterion',
          'adGroupId': ad_group_id,
          # Create a webpage criterion for special offers for children.
          'criterion': {
              'xsi_type': 'Webpage',
              'parameter': {
                  'criterionName': 'Special offers for children.',
                  'conditions': [
                      {
                          'operand': 'URL',
                          'argument': '/marscruise/children'
                      },
                      {
                          'operand': 'PAGE_TITLE',
                          'argument': 'Special Offer'
                      }
                  ]
              }
          },
          'userStatus': 'PAUSED',
          # Optional: set a custom bid.
          'biddingStrategyConfiguration': {
              'bids': [{
                  'xsi_type': 'CpcBid',
                  'bid': {
                      'microAmount': 10000000L
                  }
              }]
          }
      }
  }]

  criterion = ad_group_criterion_service.mutate(operations)['value'][0]

  print 'Webpage criterion with ID "%d" was added to ad group ID "%d".' % (
      criterion['criterion']['id'], criterion['adGroupId'])


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client)

Add an expanded text ad with Upgraded URLs

#!/usr/bin/env python
#
# Copyright 2016 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 adds an expanded text ad that uses upgraded URLS.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""

from googleads import adwords
from googleads import errors


ADGROUP_ID = 'INSERT_ADGROUP_ID_HERE'


def main(client, adgroup_id):
  # Initialize appropriate service.
  adgroup_ad_service = client.GetService('AdGroupAdService', version='v201710')

  # Create the expanded text ad
  expanded_text_ad = {
      'xsi_type': 'ExpandedTextAd',
      'headlinePart1': 'Luxury Cruise to Mars',
      'headlinePart2': 'Visit the Red Planet in style.',
      'description': 'Low-gravity fun for everyone!',
      # Specify a tracking URL for 3rd party tracking provider. You may specify
      # one at customer, campaign, ad group, ad, criterion or feed item levels.
      'trackingUrlTemplate': ('http://tracker.example.com/?season={_season}'
                              '&promocode={_promocode}&u={lpurl}'),
      'urlCustomParameters': {
          'parameters': [
              # Since your tracking URL has two custom parameters, provide
              # their values too. This can be provided at campaign, ad group,
              # ad, criterion, or feed item levels.
              {
                  'key': 'season',
                  'value': 'christmas'
              },
              {
                  'key': 'promocode',
                  'value': 'NYC123'
              }
          ]
      },
      # Specify a list of final URLs. This field cannot be set if URL
      # field is set, or finalUrls is unset. This may be specified at ad,
      # criterion, and feed item levels.
      'finalUrls': [
          'http://www.example.com/cruise/space/',
          'http://www.example.com/locations/mars/'
      ],
      # Specify a list of final mobile URLs. This field cannot be set if URL
      # field is set, or finalUrls is unset. This may be specified at ad,
      # criterion, and feed item levels.
      'finalMobileUrls': [
          'http://mobile.example.com/cruise/space/',
          'http://mobile.example.com/locations/mars/'
      ]
  }

  text_adgroup_ad = {
      'adGroupId': adgroup_id,
      'ad': expanded_text_ad,
      # Optional: Set the status.
      'status': 'PAUSED'
  }

  operations = [{
      'operator': 'ADD',
      'operand': text_adgroup_ad
  }]

  response = adgroup_ad_service.mutate(operations)

  if 'value' in response:
    for adgroup_ad in response['value']:
      print 'AdGroupAd with ID "%s" was added.' % adgroup_ad['ad']['id']
      print 'Upgraded URL properties:'
      print 'Final Urls: %s' % adgroup_ad['ad']['finalUrls']
      print 'Final Mobile URLs: %s' % adgroup_ad['ad']['finalMobileUrls']
      print ('Tracking URL template: %s'
             % adgroup_ad['ad']['trackingUrlTemplate'])
      print 'Custom parameters: %s' % adgroup_ad['ad']['urlCustomParameters']
  else:
    raise errors.GoogleAdsError('Failed to create AdGroupAd.')


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client, ADGROUP_ID)

Add an HTML 5 ad to an ad group

#!/usr/bin/env python
#
# Copyright 2016 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 adds an HTML5 ad to a given AdGroup.

To get ad_group_id, run get_ad_groups.py.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""


import base64
import urllib2
from googleads import adwords


AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE'


def main(client, ad_group_id):
  # Initialize appropriate service.
  ad_group_ad_service = client.GetService('AdGroupAdService', version='v201710')

  # Create HTML5 media.
  base64_encoded_html5_zip = GetBase64EncodedHTML5ZipFromUrl(
      'https://goo.gl/9Y7qI2')
  # Create a media bundle containing the zip file with all the HTML5 components.
  media_bundle = {
      'xsi_type': 'MediaBundle',
      'data': base64_encoded_html5_zip,
      'entryPoint': 'carousel/index.html',
      'type': 'MEDIA_BUNDLE'
  }

  ad_data = {
      'uniqueName': 'adData',
      'fields': [
          {
              'name': 'Custom_layout',
              'fieldMedia': media_bundle,
              'type': 'MEDIA_BUNDLE'
          },
          {
              'name': 'layout',
              'fieldText': 'Custom',
              'type': 'ENUM'
          }
      ]
  }

  html5_ad = {
      'xsi_type': 'TemplateAd',
      'name': 'Ad for HTML5',
      'templateId': 419,
      'finalUrls': ['https://www.google.com'],
      'displayUrl': 'www.google.com?tip=ENTER_YOUR_OWN_FINAL_AND_DISPLAY_URLS',
      'dimensions': {
          'width': '300',
          'height': '250'
      },
      'templateElements': [ad_data]
  }

  ad_group_ad = {
      'adGroupId': ad_group_id,
      'ad': html5_ad,
      'status': 'PAUSED'
  }

  operations = [
      {
          'operator': 'ADD',
          'operand': ad_group_ad
      }
  ]
  ads = ad_group_ad_service.mutate(operations)

  # Display results.
  for ad in ads['value']:
    print ('New HTML5 Ad with id "%s" and of display url "%s" was added.'
           % (ad['ad']['id'], ad['ad']['displayUrl']))


def GetBase64EncodedHTML5ZipFromUrl(url):
  """Retrieve zip file from the given URL."""
  response = urllib2.urlopen(url)
  # Note: The utf-8 decode is for 2to3 Python 3 compatibility.
  return base64.b64encode(response.read()).decode('utf-8')


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client, AD_GROUP_ID)

Add responsive ads

#!/usr/bin/env python
#
# Copyright 2016 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 adds a responsive display ad to a given ad group.

To get ad_group_id, run get_ad_groups.py.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""

import base64
import urllib2

from googleads import adwords


AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE'


def main(client, ad_group_id):
  # Initialize appropriate services.
  ad_group_ad_service = client.GetService('AdGroupAdService', version='v201710')
  media_service = client.GetService('MediaService', version='v201710')
  opener = urllib2.build_opener(*client.proxy_config.GetHandlers())

  try:
    # Create marketing image.
    marketing_image = _CreateImage(media_service, opener,
                                   'https://goo.gl/3b9Wfh')

    # Create square marketing image.
    square_marketing_image = _CreateImage(media_service, opener,
                                          'https://goo.gl/mtt54n')

    # Create a responsive display ad.
    operations = [{
        'operator': 'ADD',
        'operand': {
            'xsi_type': 'AdGroupAd',
            'adGroupId': ad_group_id,
            'ad': {
                'xsi_type': 'ResponsiveDisplayAd',
                'marketingImage': {'mediaId': marketing_image['mediaId']},
                'shortHeadline': 'Travel',
                'longHeadline': 'Travel the World',
                'description': 'Take to the air!',
                'businessName': 'Interplanetary Cruises',
                'finalUrls': ['http://www.example.com'],
                # Optional: Set a square marketing image to the ad.
                'squareMarketingImage': {
                    'mediaId': square_marketing_image['mediaId']
                },
                # Optional: Set call-to-action text.
                'callToActionText': 'Shop Now',
                # Optional: Set dynamic display ad settings, composed of
                # landscape logo image, promotion text, and price prefix.
                'dynamicDisplayAdSettings': _CreateDynamicDisplayAdSettings(
                    media_service, opener),
                # Whitelisted accounts only: Set color settings using
                # hexadecimal numbers.
                # Set allowFlexibleColor to False if you want your ads to render
                # by always using your colors strictly.
                # 'mainColor': '#0000ff',
                # 'accentColor': '#ffff00',
                # 'allowFlexibleColor': False
                # Whitelisted accounts only: Set the format setting that the ad
                # will be served in.
                # 'formatSetting': 'NON_NATIVE'

            },
            # Optional fields.
            'status': 'PAUSED'
        }
    }]

    # Make the mutate request.
    ads = ad_group_ad_service.mutate(operations)

    # Display results.
    for ad in ads['value']:
      print ('ResponsiveDisplayAd with id "%d" and short headline "%s" was '
             'added.' % (ad['ad']['id'], ad['ad']['shortHeadline']))

  except:
    raise Exception('Failed to create responsive display ad.')


def _CreateImage(media_service, opener, url):
  """Creates an image and uploads it to the server.

  Args:
    media_service: a SudsServiceProxy instance for AdWords's MediaService.
    opener: an OpenerDirector instance.
    url: a str URL used to load image data.

  Returns:
    The image that was successfully uploaded.
  """
  # Note: The utf-8 decode is for 2to3 Python 3 compatibility.
  image_data = base64.b64encode(opener.open(url).read()).decode('utf-8')
  image = {
      'type': 'IMAGE',
      'data': image_data,
      'xsi_type': 'Image'
  }

  return media_service.upload(image)[0]


def _CreateDynamicDisplayAdSettings(media_service, opener):
  """Creates settings for dynamic display ad.

  Args:
    media_service: a SudsServiceProxy instance for AdWords's MediaService.
    opener: an OpenerDirector instance.

  Returns:
    The dynamic display ad settings.
  """
  image = _CreateImage(media_service, opener, 'https://goo.gl/dEvQeF')

  logo = {
      'type': 'IMAGE',
      'mediaId': image['mediaId'],
      'xsi_type': 'Image'
  }

  dynamic_settings = {
      'landscapeLogoImage': logo,
      'pricePrefix': 'as low as',
      'promoText': 'Free shipping!',
      'xsi_type': 'DynamicSettings',
  }

  return dynamic_settings


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client, AD_GROUP_ID)

Add a universal app campaign

#!/usr/bin/env python
#
# Copyright 2016 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 adds a Universal App campaign.

To get campaigns, run get_campaigns.py. To upload image assets for this
campaign, run upload_image.py.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""


import datetime
import uuid
from googleads import adwords


def main(client):
  # Initialize appropriate services.
  campaign_service = client.GetService('CampaignService', version='v201710')

  budget_id = CreateBudget(client)

  # Create the Universal App campaign.
  universal_app_campaign = {
      'name': 'Interplanetary Cruise App #%s' % uuid.uuid4(),
      # Recommendation: Set the campaign to PAUSED when creating it to stop the
      # ads from immediately serving. Set to ENABLED once you've added targeting
      # and the ads are ready to serve.
      'status': 'PAUSED',
      'advertisingChannelType': 'MULTI_CHANNEL',
      'advertisingChannelSubType': 'UNIVERSAL_APP_CAMPAIGN',
      # Set the campaign's bidding strategy. Universal app campaigns only
      # support TARGET_CPA bidding strategy.
      'biddingStrategyConfiguration': {
          # Set the target CPA to $1 / app install.
          'biddingScheme': {
              'xsi_type': 'TargetCpaBiddingScheme',
              'targetCpa': {
                  'microAmount': '1000000'
              }
          },
          'biddingStrategyType': 'TARGET_CPA'
      },
      # Note that only the budgetId is required
      'budget': {
          'budgetId': budget_id
      },
      # Optional fields
      'startDate': (datetime.datetime.now() +
                    datetime.timedelta(1)).strftime('%Y%m%d'),
      'endDate': (datetime.datetime.now() +
                  datetime.timedelta(365)).strftime('%Y%m%d'),
  }

  universal_app_campaign['settings'] = [
      # Set the campaign's assets and ad text ideas. These values will
      # be used to generate ads.
      {
          'xsi_type': 'UniversalAppCampaignSetting',
          'appId': 'com.labpixies.colordrips',
          'description1': 'A cool puzzle game',
          'description2': 'Remove connected blocks',
          'description3': '3 difficulty levels',
          'description4': '4 colorful fun skins',
          # Optional: You can set up to 20 image assets for your campaign.
          # See upload_image.py for an example on how to upload images.
          #
          # 'imageMediaIds': [INSERT_IMAGE_MEDIA_ID(s)_HERE]
      }
  ]

  # Optimize this campaign for getting new users for your app.
  universal_app_campaign_setting = universal_app_campaign['settings'][0]
  universal_app_campaign_setting['universalAppBiddingStrategyGoalType'] = (
      'OPTIMIZE_FOR_INSTALL_CONVERSION_VOLUME')

  # Optional: If you select the OPTIMIZE_FOR_IN_APP_CONVERSION_VOLUME goal type,
  # then also specify your in-app conversion types so AdWords can focus your
  # campaign on people who are most likely to complete the corresponding in-app
  # actions.
  #
  # Conversions type IDs can be retrieved using ConversionTrackerService.get.
  # universal_app_campaign['selectiveOptimization'] = {
  #     'conversionTypeIds': [INSERT_CONVERSION_TYPE_ID(s)_HERE]
  # }

  # Optional: Set the campaign settings for Advanced location options.
  universal_app_campaign['settings'].append({
      'xsi_type': 'GeoTargetTypeSetting',
      'positiveGeoTargetType': 'DONT_CARE',
      'negativeGeoTargetType': 'DONT_CARE'
  })

  # Construct operations and add campaigns.
  operations = [{
      'operator': 'ADD',
      'operand': universal_app_campaign
  }]

  campaigns = campaign_service.mutate(operations)['value']

  # Display results.
  if campaigns:
    for campaign in campaigns:
      print ('Universal App Campaign with name "%s" and id "%s" was added.'
             % (campaign['name'], campaign['id']))
      # Optional: Set the campaign's location and language targeting. No other
      # targeting criteria can be used for Universal App campaigns.
      SetCampaignTargetingCriteria(client, campaign)
  else:
    print 'No Universal App campaigns were added.'


def CreateBudget(client):
  """Creates a budget and returns its budgetId.

  Args:
    client: An AdWordsClient instance.

  Returns:
    An int budgetId for the created Budget.
  """
  budget_service = client.GetService('BudgetService', version='v201710')

  # Create a budget.
  budget = {
      'name': 'Interplanetary Cruise App Budget #%s' % uuid.uuid4(),
      'amount': {
          'microAmount': '50000000'
      },
      'deliveryMethod': 'STANDARD',
      'isExplicitlyShared': False
  }

  budget_operations = [{
      'operator': 'ADD',
      'operand': budget
  }]

  # Create the budget and return its ID.
  budget_id = budget_service.mutate(budget_operations)['value'][0]['budgetId']

  return budget_id


def SetCampaignTargetingCriteria(client, campaign):
  """Sets targeting criteria for the given campaign.

  Args:
    client: An AdWordsClient instance.
    campaign: A suds object representing the campaign we wish to attach
      targeting criteria.
  """
  campaign_criterion_service = client.GetService('CampaignCriterionService')

  # Create locations. The IDs can be found in the documentation or retrieved
  # with the LocationCriterionService.
  criteria = [
      {
          'xsi_type': 'Location',
          'id': 21137  # California
      },
      {
          'xsi_type': 'Location',
          'id': 2484  # Mexico
      },
      {
          'xsi_type': 'Language',
          'id': 1000  # English
      },
      {
          'xsi_type': 'Language',
          'id': 1003  # Spanish
      }
  ]

  operations = [{
      'operator': 'ADD',
      'operand': {
          'campaignId': campaign['id'],
          'criterion': criterion
      }
  } for criterion in criteria]

  response = campaign_criterion_service.mutate(operations)

  if response and 'value' in response:
    # Display the added campaign targets.
    for criterion in response['value']:
      print ('Campaign criteria of type "%s" and id "%s" was added.'
             % (criterion['criterion']['type'],
                criterion['criterion']['id']))


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client)

Create and attach a shared keyword set

#!/usr/bin/env python
#
# Copyright 2016 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.

"""Attaches a new shared list of negative broad match keywords to a campaign.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""


import uuid
from googleads import adwords
from googleads import errors


CAMPAIGN_ID = 'INSERT_CAMPAIGN_ID_HERE'


def main(client, campaign_id):
  # Initialize appropriate services.
  shared_set_service = client.GetService('SharedSetService', version='v201710')
  shared_criterion_service = client.GetService('SharedCriterionService',
                                               version='v201710')
  campaign_shared_set_service = client.GetService('CampaignSharedSetService',
                                                  version='v201710')

  # Keywords to create a shared set of.
  keywords = ['mars cruise', 'mars hotels']
  # Create shared negative keyword set.
  shared_set = {
      'name': 'API Negative keyword list - %d' % uuid.uuid4(),
      'type': 'NEGATIVE_KEYWORDS'
  }

  # Add shared set.
  operations = [{
      'operator': 'ADD',
      'operand': shared_set
  }]

  response = shared_set_service.mutate(operations)

  if response and response['value']:
    shared_set = response['value'][0]
    shared_set_id = shared_set['sharedSetId']

    print 'Shared set with ID %d and name "%s" was successfully added.' % (
        shared_set_id, shared_set['name']
    )
  else:
    raise errors.GoogleAdsError('No shared set was added.')

    # Add negative keywords to shared set.
  shared_criteria = [
      {
          'criterion': {
              'xsi_type': 'Keyword',
              'text': keyword,
              'matchType': 'BROAD'
          },
          'negative': True,
          'sharedSetId': shared_set_id
      } for keyword in keywords
  ]

  operations = [
      {
          'operator': 'ADD',
          'operand': criterion
      } for criterion in shared_criteria
  ]

  response = shared_criterion_service.mutate(operations)

  if 'value' in response:
    for shared_criteria in response['value']:
      print 'Added shared criterion ID %d "%s" to shared set with ID %d.' % (
          shared_criteria['criterion']['id'],
          shared_criteria['criterion']['text'],
          shared_criteria['sharedSetId']
      )
  else:
    raise errors.GoogleAdsError('No shared keyword was added.')

    # Attach the articles to the campaign.
  campaign_set = {
      'campaignId': campaign_id,
      'sharedSetId': shared_set_id
  }

  operations = [
      {
          'operator': 'ADD',
          'operand': campaign_set
      }
  ]

  response = campaign_shared_set_service.mutate(operations)

  if 'value' in response:
    print 'Shared set ID %d was attached to campaign ID %d' % (
        response['value'][0]['sharedSetId'], response['value'][0]['campaignId']
    )
  else:
    raise errors.GoogleAdsError('No campaign shared set was added.')


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client, CAMPAIGN_ID)

Find and remove criteria from a shared set

#!/usr/bin/env python
#
# Copyright 2016 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.

"""Demonstrates how to find and remove shared sets/shared set criterions.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""

from googleads import adwords


CAMPAIGN_ID = 'INSERT_CAMPAIGN_ID_HERE'
PAGE_SIZE = 500


def main(client, campaign_id):
  # Initialize appropriate services.
  shared_criterion_service = client.GetService('SharedCriterionService',
                                               version='v201710')
  campaign_shared_set_service = client.GetService('CampaignSharedSetService',
                                                  version='v201710')

  shared_set_ids = []
  criterion_ids = []

  # First, retrieve all shared sets associated with the campaign.

  # Create selector for shared sets to:
  # - filter by campaign ID,
  # - filter by shared set type.
  selector = {
      'fields': ['SharedSetId', 'CampaignId', 'SharedSetName', 'SharedSetType',
                 'Status'],
      'predicates': [
          {
              'field': 'CampaignId',
              'operator': 'EQUALS',
              'values': [campaign_id]
          },
          {
              'field': 'SharedSetType',
              'operator': 'IN',
              'values': ['NEGATIVE_KEYWORDS', 'NEGATIVE_PLACEMENTS']
          }
      ],
      'paging': {
          'startIndex': 0,
          'numberResults': PAGE_SIZE
      }
  }

  # Set initial values:
  offset = 0
  page = {'totalNumEntries': 1}

  while page['totalNumEntries'] > offset:
    page = campaign_shared_set_service.get(selector)
    if 'entries' in page:
      for shared_set in page['entries']:
        print 'Campaign shared set ID %d and name "%s"' % (
            shared_set['sharedSetId'], shared_set['sharedSetName']
        )
        shared_set_ids.append(shared_set['sharedSetId'])
    # Increment values to request the next page.
    offset += PAGE_SIZE
    selector['paging']['startIndex'] = offset

  # Next, retrieve criterion IDs for all found shared sets.
  selector = {
      'fields': ['SharedSetId', 'Id', 'KeywordText', 'KeywordMatchType',
                 'PlacementUrl'],
      'predicates': [
          {
              'field': 'SharedSetId',
              'operator': 'IN',
              'values': shared_set_ids
          }
      ],
      'paging': {
          'startIndex': 0,
          'numberResults': PAGE_SIZE
      }
  }

  # Set initial values:
  offset = 0
  page = {'totalNumEntries': 1}

  while page['totalNumEntries'] > offset:
    page = shared_criterion_service.get(selector)
    if 'entries' in page:
      for shared_criterion in page['entries']:
        if shared_criterion['criterion']['type'] == 'KEYWORD':
          print ('Shared negative keyword with ID %d and text "%s" was'
                 'found.' % (shared_criterion['criterion']['id'],
                             shared_criterion['criterion']['text']))
        elif shared_criterion['criterion']['type'] == 'PLACEMENT':
          print ('Shared negative placement with ID %d and url "%s" was'
                 'found.' % (shared_criterion['criterion']['id'],
                             shared_criterion['criterion']['url']))
        else:
          print 'Shared criterion with ID %d was found.' % (
              shared_criterion['criterion']['id'],
          )
        criterion_ids.append({
            'sharedSetId': shared_criterion['sharedSetId'],
            'criterionId': shared_criterion['criterion']['id']
        })
    # Increment values to request the next page.
    offset += PAGE_SIZE
    selector['paging']['startIndex'] = offset

  # Finally, remove the criteria.
  if criterion_ids:
    operations = [
        {
            'operator': 'REMOVE',
            'operand': {
                'criterion': {'id': criterion['criterionId']},
                'sharedSetId': criterion['sharedSetId']
            }
        } for criterion in criterion_ids
    ]

    response = shared_criterion_service.mutate(operations)
    if 'value' in response:
      for criterion in response['value']:
        print ('Criterion ID %d was successfully removed from shared set ID'
               '%d.' % (criterion['criterion']['id'], criterion['sharedSetId']))
  else:
    print 'No shared criteria were removed.'


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client, CAMPAIGN_ID)

Get ad group bid modifiers

#!/usr/bin/env python
#
# Copyright 2016 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.

"""Retrieves the ad group level bid modifiers for a campaign.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""

from googleads import adwords


PAGE_SIZE = 500


def main(client):
  # Initialize appropriate service.
  ad_group_bid_modifier_service = client.GetService(
      'AdGroupBidModifierService', version='v201710')

  # Get all ad group bid modifiers for the campaign.
  selector = {
      'fields': ['CampaignId', 'AdGroupId', 'BidModifier', 'Id'],
      'paging': {
          'startIndex': '0',
          'numberResults': str(PAGE_SIZE)
      }
  }

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

  while more_results:
    page = ad_group_bid_modifier_service.get(selector)
    if page['entries']:
      for modifier in page['entries']:
        value = (modifier['bidModifier'] if 'bidModifier' in modifier
                 else 'unset')
        print ('Campaign ID %s, AdGroup ID %s, Criterion ID %s has ad group '
               'level modifier: %s' %
               (modifier['campaignId'], modifier['adGroupId'],
                modifier['criterion']['id'], value))

      # Increment values to request the next page.
      offset += PAGE_SIZE
      selector['paging']['startIndex'] = str(offset)
    else:
      print 'No ad group bid modifiers returned.'
    more_results = int(page['totalNumEntries']) > offset


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client)

Use a shared bidding strategy

#!/usr/bin/env python
#
# Copyright 2016 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.

"""Adds a Shared Bidding Strategy and uses it to construct a campaign.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""


import uuid
from googleads import adwords


# Enter a shared budget ID to re-use an existing budget or leave as None to
# create a new one.
BUDGET_ID = None


def main(client, budget_id):
  bidding_strategy = CreateBiddingStrategy(client)

  if budget_id is None:
    budget = CreateSharedBudget(client)
    budget_id = budget['budgetId']

  CreateCampaignWithBiddingStrategy(client, bidding_strategy['id'], budget_id)


def CreateBiddingStrategy(client):
  """Creates a bidding strategy object.

  Args:
    client: AdWordsClient the client to run the example with.

  Returns:
    dict An object representing a bidding strategy.
  """
  # Initialize appropriate service.
  bidding_strategy_service = client.GetService(
      'BiddingStrategyService', version='v201710')

  # Create a shared bidding strategy.
  shared_bidding_strategy = {
      'name': 'Maximize Clicks %s' % uuid.uuid4(),
      'biddingScheme': {
          'xsi_type': 'TargetSpendBiddingScheme',
          # Optionally set additional bidding scheme parameters.
          'bidCeiling': {
              'microAmount': '2000000'
          }
      }
  }

  # Create operation.
  operation = {
      'operator': 'ADD',
      'operand': shared_bidding_strategy
  }

  response = bidding_strategy_service.mutate([operation])
  new_bidding_strategy = response['value'][0]

  print ('Shared bidding strategy with name "%s" and ID "%s" of type "%s"'
         'was created.' %
         (new_bidding_strategy['name'], new_bidding_strategy['id'],
          new_bidding_strategy['biddingScheme']['BiddingScheme.Type']))

  return new_bidding_strategy


def CreateSharedBudget(client):
  """Creates an explicit budget to be used only to create the Campaign.

  Args:
    client: AdWordsClient the client to run the example with.

  Returns:
    dict An object representing a shared budget.
  """
  # Initialize appropriate service.
  budget_service = client.GetService('BudgetService', version='v201710')

  # Create a shared budget
  budget = {
      'name': 'Shared Interplanetary Budget #%s' % uuid.uuid4(),
      'amount': {
          'microAmount': '2000000'
      },
      'deliveryMethod': 'STANDARD',
      'isExplicitlyShared': 'true'
  }

  # Create operation.
  operation = {
      'operator': 'ADD',
      'operand': budget
  }

  response = budget_service.mutate([operation])
  return response['value'][0]


def CreateCampaignWithBiddingStrategy(client, bidding_strategy_id, budget_id):
  """Create a Campaign with a Shared Bidding Strategy.

  Args:
    client: AdWordsClient the client to run the example with.
    bidding_strategy_id: string the bidding strategy ID to use.
    budget_id: string the shared budget ID to use.

  Returns:
    dict An object representing a campaign.
  """
  # Initialize appropriate service.
  campaign_service = client.GetService('CampaignService', version='v201710')

  # Create campaign.
  campaign = {
      'name': 'Interplanetary Cruise #%s' % uuid.uuid4(),
      'budget': {
          'budgetId': budget_id
      },
      'biddingStrategyConfiguration': {
          'biddingStrategyId': bidding_strategy_id
      },
      'advertisingChannelType': 'SEARCH',
      'networkSetting': {
          'targetGoogleSearch': 'true',
          'targetSearchNetwork': 'true',
          'targetContentNetwork': 'true'
      }
  }

  # Create operation.
  operation = {
      'operator': 'ADD',
      'operand': campaign
  }

  response = campaign_service.mutate([operation])
  new_campaign = response['value'][0]

  print ('Campaign with name "%s", ID "%s" and bidding scheme ID "%s" '
         'was created.' %
         (new_campaign['name'], new_campaign['id'],
          new_campaign['biddingStrategyConfiguration']['biddingStrategyId']))

  return new_campaign


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()
  main(adwords_client, BUDGET_ID)

Send feedback about...

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