Skip to content

Instantly share code, notes, and snippets.

@nitobuendia
Last active August 14, 2018 09:46
Show Gist options
  • Save nitobuendia/a6760dd853f896d6fc8ef4c1993876cd to your computer and use it in GitHub Desktop.
Save nitobuendia/a6760dd853f896d6fc8ef4c1993876cd to your computer and use it in GitHub Desktop.
Retrieves price extensions details at different levels from a Google Ads account.
"""Retrieves price extensions details (at any level, on the data feeds) from a Google Ads account.
If you never installed Google Ads API before, you may need to install it first:
https://github.com/googleads/googleads-python-lib/blob/master/README.md#getting-started
$ pip install setuptools
$ pip install googleads
$ pip install google-auth-oauthlib
In order to use this script, some pre-configuration is needed:
https://developers.google.com/adwords/api/docs/guides/first-api-call
1. Get a Google Ads developer token.
https://developers.google.com/adwords/api/docs/guides/first-api-call#request_a_developer_token
2. Get a client id and secret for OAuth2.
https://developers.google.com/adwords/api/docs/guides/authentication#installed
3. Generate a refresh token.
https://github.com/googleads/googleads-python-lib/wiki/API-access-using-own-credentials-(installed-application-flow)#step-2---setting-up-the-client-library
4. Configure your googleads.yaml file with the following contents:
https://github.com/googleads/googleads-python-lib/blob/master/googleads.yaml
adwords:
developer_token: XXX
user_agent: Your_Name
client_customer_id: XXX-XXX-XXXX
client_id: XXX
client_secret: XXX
refresh_token: XXX
Instructions for step 4:
Replace developer_token value with the token from step 1.
Replace user_agent value with your name or app name.
Replace client_customer_id with the Google Ads account in which you want to operate.
Replace client_id and client_secret values for the details generated in step 2.
Replace refresh_token value with the value generated on step 3.
>> Step 3 and this value may need to be updated if not run in a few hours.
"""
from googleads import adwords
API_VERSION = 'v201806'
# See map of attributes for your desired extension:
# https://developers.google.com/adwords/api/docs/appendix/placeholders#price
# Note: for some reason, ITEM_X_ATTRIBUTES do not seem to map to 3 digits id.
# However, keeping this as a map for easy update in case of needing it in the
# future.
EXTENSION_ATTRIBUTE_ID_TO_NAME_MAP = {
'1': 'TYPE',
'2': 'PRICE_QUALIFIER',
'3': 'TRACKING',
'4': 'LANGUAGE',
'5': 'FINAL',
'6': 'ITEM_1_HEADER',
'7': 'ITEM_1_DESCRIPTION',
'8': 'ITEM_1_PRICE',
'9': 'ITEM_1_UNIT',
'10': 'ITEM_1_FINAL_URL',
'11': 'ITEM_1_FINAL_MOBILE_URL',
'12': 'ITEM_2_HEADER',
'13': 'ITEM_2_DESCRIPTION',
'14': 'ITEM_2_PRICE',
'15': 'ITEM_2_UNIT',
'16': 'ITEM_2_FINAL_URL',
'17': 'ITEM_2_FINAL_MOBILE_URL',
'18': 'ITEM_3_HEADER',
'19': 'ITEM_3_DESCRIPTION',
'20': 'ITEM_3_PRICE',
'21': 'ITEM_3_UNIT',
'22': 'ITEM_3_FINAL_URL',
'23': 'ITEM_3_FINAL_MOBILE_URL',
'24': 'ITEM_4_HEADER',
'25': 'ITEM_4_DESCRIPTION',
'26': 'ITEM_4_PRICE',
'27': 'ITEM_4_UNIT',
'28': 'ITEM_4_FINAL_URL',
'29': 'ITEM_4_FINAL_MOBILE_URL',
'30': 'ITEM_5_HEADER',
'31': 'ITEM_5_DESCRIPTION',
'32': 'ITEM_5_PRICE',
'33': 'ITEM_5_UNIT',
'34': 'ITEM_5_FINAL_URL',
'35': 'ITEM_5_FINAL_MOBILE_URL',
'36': 'ITEM_6_HEADER',
'37': 'ITEM_6_DESCRIPTION',
'38': 'ITEM_6_PRICE',
'39': 'ITEM_6_UNIT',
'40': 'ITEM_6_FINAL_URL',
'41': 'ITEM_6_FINAL_MOBILE_URL',
'42': 'ITEM_7_HEADER',
'43': 'ITEM_7_DESCRIPTION',
'44': 'ITEM_7_PRICE',
'45': 'ITEM_7_UNIT',
'46': 'ITEM_7_FINAL_URL',
'47': 'ITEM_7_FINAL_MOBILE_URL',
'48': 'ITEM_8_HEADER',
'49': 'ITEM_8_DESCRIPTION',
'50': 'ITEM_8_PRICE',
'51': 'ITEM_8_UNIT',
'52': 'ITEM_8_FINAL_URL',
'53': 'ITEM_8_FINAL_MOBILE_URL',
}
def main(client):
"""Prints extensions data for a given placeholder type.
Args:
client: AdWordsClient, An AdWords client.
"""
# See values for Placeholder Type ID:
# https://developers.google.com/adwords/api/docs/appendix/placeholders
placeholder_type = '35' # Price extensions placeholder type.
price_extensions = get_all_extensions_by_type(client, placeholder_type)
if not price_extensions.entries:
print('No extensions found.')
return
print('Found {} extension(s):'.format(price_extensions.totalNumEntries))
for price_extension in price_extensions.entries:
# Add your logic for printing or handling each extension.
print("""
Price Extension:
> FEED_ID: {feed_id}
> EXTENSION_ID: {feed_item_id}
> STATUS: {status}
> START_TIME: {start_time}
> END_TIME: {end_time}""".format(
feed_id=price_extension.feedId,
feed_item_id=price_extension.feedItemId,
start_time=price_extension.startTime,
end_time=price_extension.endTime,
status=price_extension.status,
))
for feed_item_attribute in price_extension.attributeValues:
print(' > {attribute_name}: {attribute_value}'.format(
attribute_name=get_feed_item_attribute_name(feed_item_attribute),
attribute_value=get_feed_item_attribute_value(feed_item_attribute),
))
def get_feed_item_attribute_name(feed_item_attribute):
"""Gets the name of an attribute value.
Args:
feed_item_attribute: FeedItemAttributeValue, Feed item attribute.
Returns:
Name for the given feed item attribute.
"""
attribute_id = str(feed_item_attribute.feedAttributeId)
default_value = 'Unknown (ID: {})'.format(attribute_id)
return EXTENSION_ATTRIBUTE_ID_TO_NAME_MAP.get(attribute_id, default_value)
def get_feed_item_attribute_value(feed_item_attribute):
"""Gets the value of an feed item attribute.
Args:
feed_item_attribute: FeedItemAttributeValue, Feed item attribute.
Returns:
Value for the given feed item attribute.
"""
base_attribute_value = (
feed_item_attribute.integerValue or
feed_item_attribute.doubleValue or
feed_item_attribute.booleanValue or
feed_item_attribute.stringValue
)
list_attribute_value = ', '.join(
feed_item_attribute.integerValues or
feed_item_attribute.doubleValues or
feed_item_attribute.booleanValues or
feed_item_attribute.stringValues or
[]
)
micros_attribute_value = feed_item_attribute.moneyWithCurrencyValue
if micros_attribute_value:
micros_attribute_value = '{currency_code} {amount}'.format(
currency_code=micros_attribute_value.currencyCode,
amount=round(micros_attribute_value.money.microAmount / 1e6, 2)
)
return base_attribute_value or list_attribute_value or micros_attribute_value
def get_all_extensions_by_type(client, extension_type):
"""Gets all extensions of a certain extension placeholder type.
Args:
client: AdWordsClient, An AdWords client.
extension_type: str|int|List[Union[str,int]] Placeholder type of extension.
Returns:
List of feed item ids for given feed placeholder type.
"""
feed_ids = get_feed_ids_by_extension_type(client, extension_type)
feed_items = get_feed_items_by_feed_id(client, feed_ids)
return feed_items
def get_feed_ids_by_extension_type(client, extension_type):
"""Gets all feed ids which holds extensions of a certain placeholder type.
Args:
client: AdWordsClient, An AdWords client.
extension_type: str|int|List[Union[str,int]] Placeholder type of extension.
Returns:
List of feed ids for given feed placeholder type.
"""
feed_mapping_service = client.GetService('FeedMappingService', API_VERSION)
if isinstance(extension_type, str):
extension_type = [extension_type]
selector = {
'fields': ['FeedId', 'Status'],
'predicates': [
{
'field': 'PlaceholderType',
'operator': 'IN',
'values': extension_type,
}
]
}
feeds = feed_mapping_service.get(selector)
feed_ids = []
for feed in feeds.entries:
feed_ids.append(feed.feedId)
return feed_ids
def get_feed_items_by_feed_id(client, feed_ids):
"""Gets all feed items (extensions) of a certain extension placeholder type.
Args:
client: AdWordsClient, An AdWords client.
feed_ids: List[int], List of feed ids from which to get all extensions.
Returns:
List of feed ids for given feed placeholder type.
"""
feed_item_service = client.GetService('FeedItemService', API_VERSION)
if not isinstance(feed_ids, list):
feed_ids = [feed_ids]
selector = {
'fields': [
'FeedId', 'FeedItemId', 'AttributeValues', 'Status', 'StartTime',
'EndTime',
],
'predicates': [
{
'field': 'FeedId',
'operator': 'IN',
'values': feed_ids,
}
]
}
feed_items = feed_item_service.get(selector)
return feed_items
if __name__ == '__main__':
# OAuth details loaded from googleads.yaml -- See instructions above.
adwords_client = adwords.AdWordsClient.LoadFromStorage(path='googleads.yaml')
main(adwords_client)
"""Retrieves price extensions details added at Customer level from a Google Ads account.
LICENSE:
Copyright 2018 Google LLC
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.
INSTRUCTIONS:
If you never installed Google Ads API before, you may need to install it first:
https://github.com/googleads/googleads-python-lib/blob/master/README.md#getting-started
$ pip install setuptools
$ pip install googleads
$ pip install google-auth-oauthlib
In order to use this script, some pre-configuration is needed:
https://developers.google.com/adwords/api/docs/guides/first-api-call
1. Get a Google Ads developer token.
https://developers.google.com/adwords/api/docs/guides/first-api-call#request_a_developer_token
2. Get a client id and secret for OAuth2.
https://developers.google.com/adwords/api/docs/guides/authentication#installed
3. Generate a refresh token.
https://github.com/googleads/googleads-python-lib/wiki/API-access-using-own-credentials-(installed-application-flow)#step-2---setting-up-the-client-library
4. Configure your googleads.yaml file with the following contents:
https://github.com/googleads/googleads-python-lib/blob/master/googleads.yaml
adwords:
developer_token: XXX
user_agent: Your_Name
client_customer_id: XXX-XXX-XXXX
client_id: XXX
client_secret: XXX
refresh_token: XXX
Instructions for step 4:
Replace developer_token value with the token from step 1.
Replace user_agent value with your name or app name.
Replace client_customer_id with the Google Ads account in which you want to operate.
Replace client_id and client_secret values for the details generated in step 2.
Replace refresh_token value with the value generated on step 3.
>> Step 3 and this value may need to be updated if not run in a few hours.
"""
from googleads import adwords
API_VERSION = 'v201806'
def main(client):
price_extensions_page = get_customer_extensions_by_type(client, 'PRICE')
if not price_extensions_page.entries:
print('No extensions found.')
return
print('Found {} extension(s):'.format(price_extensions_page.totalNumEntries))
for price_extension in price_extensions_page.entries:
for price_extension_item in price_extension.extensionSetting.extensions:
# Add your logic for printing or handling each extension.
print("""
Price Extension:
> Feed id: {feed_id}
> Extension id: {feed_item_id}
> Price Extension Type: {price_extension_type}
> Price Qualifier: {price_qualifier}
> Status: {status}
> Start Time: {start_time}
> End Time: {end_time}
""".format(
feed_id=price_extension_item.feedId,
feed_item_id=price_extension_item.feedItemId,
price_extension_type=price_extension_item.priceExtensionType,
price_qualifier=price_extension_item.priceQualifier,
start_time=price_extension_item.startTime,
end_time=price_extension_item.endTime,
status=price_extension_item.status,
))
for price_extension_item_row in price_extension_item.tableRows:
# Add your logic for printing or handling each extension price item.
print("""
> Price item:
>> Header: {header}
>> Description: {description}
>> Price in {currency} {price_amount} {price_unit}
>> Final URLs: {final_urls}
""".format(
header=price_extension_item_row.header,
description=price_extension_item_row.description,
currency=price_extension_item_row.price.currencyCode,
price_amount=price_extension_item_row.price.money.microAmount / 1e6,
price_unit=price_extension_item_row.priceUnit or '',
final_urls='\n'.join(price_extension_item_row.finalUrls.urls)
))
def get_customer_extensions_by_type(client, extension_type):
# If Campaign or AdGroup is desired: user CampaignExtensionSettingService or
# AdGroupExtensionSettingService respectively. You may want to add
# CampaignId or AdGroupId to selector['fields'].
customer_extension_setting_service = client.GetService(
'CustomerExtensionSettingService', API_VERSION)
if isinstance(extension_type, str):
extension_type = [extension_type]
selector = {
'fields': ['ExtensionType', 'Extensions'],
'predicates': [
{
'field': 'ExtensionType',
'operator': 'IN',
'values': extension_type
}
]
}
return customer_extension_setting_service.get(selector)
if __name__ == '__main__':
# OAuth details loaded from googleads.yaml -- See instructions above.
adwords_client = adwords.AdWordsClient.LoadFromStorage(path='googleads.yaml')
main(adwords_client)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment