Skip to content

Commit 5a46886

Browse files
committed
Combine Ad Responsive Search Ad With Customizer into Full example
1 parent 142debd commit 5a46886

2 files changed

Lines changed: 184 additions & 296 deletions

File tree

examples/advanced_operations/add_responsive_search_ad_full.py

Lines changed: 184 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525
import argparse
2626
import sys
2727
import uuid
28+
2829
import requests
2930

3031
from google.ads.googleads.client import GoogleAdsClient
3132
from google.ads.googleads.errors import GoogleAdsException
3233

33-
3434
# Keywords from user.
3535
_KEYWORD_TEXT_EXACT_1 = "example of exact match"
3636
_KEYWORD_TEXT_PHRASE_1 = "example of phrase match"
@@ -51,24 +51,9 @@
5151
_COUNTRY_CODE = "AR"
5252

5353

54-
def create_ad_text_asset(client, text, pinned_field=None):
55-
"""Create an AdTextAsset.
56-
Args:
57-
client: an initialized GoogleAdsClient instance.
58-
text: text for headlines and descriptions.
59-
pinned_field: to pin a text asset so it always shows in the ad.
60-
61-
Returns:
62-
An ad text asset.
63-
"""
64-
ad_text_asset = client.get_type("AdTextAsset")
65-
ad_text_asset.text = text
66-
if pinned_field:
67-
ad_text_asset.pinned_field = pinned_field
68-
return ad_text_asset
69-
70-
71-
def main(client, customer_id, omit_image_extensions):
54+
def main(
55+
client, customer_id, omit_image_extensions, customizer_attribute_name=None
56+
):
7257
"""
7358
The main method that creates all necessary entities for the example.
7459
@@ -79,6 +64,16 @@ def main(client, customer_id, omit_image_extensions):
7964
Returns:
8065
A responsive search ad with all settings required to run campaign.
8166
"""
67+
68+
if customizer_attribute_name:
69+
customizer_attribute_resource_name = create_customizer_attribute(
70+
client, customer_id, customizer_attribute_name
71+
)
72+
73+
link_customizer_attribute_to_customer(
74+
client, customer_id, customizer_attribute_resource_name
75+
)
76+
8277
# Create a budget, which can be shared by multiple campaigns.
8378
campaign_budget = create_campaign_budget(client, customer_id)
8479

@@ -90,7 +85,9 @@ def main(client, customer_id, omit_image_extensions):
9085
client, customer_id, campaign_resource_name
9186
)
9287

93-
create_ad_group_ad(client, customer_id, ad_group_resource_name)
88+
create_ad_group_ad(
89+
client, customer_id, ad_group_resource_name, customizer_attribute_name
90+
)
9491

9592
add_keywords(client, customer_id, ad_group_resource_name)
9693

@@ -104,6 +101,133 @@ def main(client, customer_id, omit_image_extensions):
104101
add_images(client, customer_id, campaign_resource_name)
105102

106103

104+
# [START add_responsive_search_ad_full_customizer_1]
105+
def create_customizer_attribute(client, customer_id, customizer_attribute_name):
106+
"""Creates a customizer attribute with the given customizer attribute name.
107+
108+
Args:
109+
client: an initialized GoogleAdsClient instance.
110+
customer_id: a client customer ID.
111+
customizer_attribute_name: the name for the customizer attribute.
112+
113+
Returns:
114+
A resource name for a customizer attribute.
115+
"""
116+
# Creates a customizer attribute operation for creating a customizer
117+
# attribute.
118+
operation = client.get_type("CustomizerAttributeOperation")
119+
# Creates a customizer attribute with the specified name.
120+
customizer_attribute = operation.create
121+
customizer_attribute.name = customizer_attribute_name
122+
# Specifies the type to be 'PRICE' so that we can dynamically customize the
123+
# part of the ad's description that is a price of a product/service we
124+
# advertise.
125+
customizer_attribute.type_ = client.enums.CustomizerAttributeTypeEnum.PRICE
126+
127+
# Issues a mutate request to add the customizer attribute and prints its
128+
# information.
129+
customizer_attribute_service = client.get_service(
130+
"CustomizerAttributeService"
131+
)
132+
response = customizer_attribute_service.mutate_customizer_attributes(
133+
customer_id=customer_id, operations=[operation]
134+
)
135+
resource_name = response.results[0].resource_name
136+
137+
print(f"Added a customizer attribute with resource name: '{resource_name}'")
138+
139+
return resource_name
140+
141+
142+
# [END add_responsive_search_ad_full_customizer_1]
143+
144+
145+
# [START add_responsive_search_full_customizer_2]
146+
def link_customizer_attribute_to_customer(
147+
client, customer_id, customizer_attribute_resource_name
148+
):
149+
"""Links the customizer attribute to the customer.
150+
151+
This is done by providing a value to be used in a responsive search ad
152+
that will be created in a later step.
153+
154+
Args:
155+
client: an initialized GoogleAdsClient instance.
156+
customer_id: a client customer ID.
157+
customizer_attribute_resource_name: a resource name for customizer
158+
attribute.
159+
"""
160+
# Creates a customer customizer operation.
161+
operation = client.get_type("CustomerCustomizerOperation")
162+
# Creates a customer customizer with the value to be used in the responsive
163+
# search ad.
164+
customer_customizer = operation.create
165+
customer_customizer.customizer_attribute = (
166+
customizer_attribute_resource_name
167+
)
168+
customer_customizer.value.type_ = (
169+
client.enums.CustomizerAttributeTypeEnum.PRICE
170+
)
171+
# Specify '100USD' as a text value. The ad customizer will dynamically
172+
# replace the placeholder with this value when the ad serves.
173+
customer_customizer.value.string_value = "100USD"
174+
175+
customer_customizer_service = client.get_service(
176+
"CustomerCustomizerService"
177+
)
178+
# Issues a mutate request to add the customer customizer and prints its
179+
# information.
180+
response = customer_customizer_service.mutate_customer_customizers(
181+
customer_id=customer_id, operations=[operation]
182+
)
183+
resource_name = response.results[0].resource_name
184+
185+
print(f"Added a customer customizer with resource name: '{resource_name}'")
186+
187+
188+
# [END add_responsive_search_full_customizer_2]
189+
190+
191+
def create_ad_text_asset(client, text, pinned_field=None):
192+
"""Create an AdTextAsset.
193+
Args:
194+
client: an initialized GoogleAdsClient instance.
195+
text: text for headlines and descriptions.
196+
pinned_field: to pin a text asset so it always shows in the ad.
197+
198+
Returns:
199+
An ad text asset.
200+
"""
201+
ad_text_asset = client.get_type("AdTextAsset")
202+
ad_text_asset.text = text
203+
if pinned_field:
204+
ad_text_asset.pinned_field = pinned_field
205+
return ad_text_asset
206+
207+
208+
def create_ad_text_asset_with_customizer(client, customizer_attribute_name):
209+
"""Create an AdTextAsset.
210+
Args:
211+
client: an initialized GoogleAdsClient instance.
212+
customizer_attribute_name: The resource Name of the customizer attribute.
213+
214+
Returns:
215+
An ad text asset.
216+
"""
217+
ad_text_asset = client.get_type("AdTextAsset")
218+
219+
# Creates this particular description using the ad customizer. Visit
220+
# https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#ad_customizers_in_responsive_search_ads
221+
# for details about the placeholder format. The ad customizer replaces the
222+
# placeholder with the value we previously created and linked to the
223+
# customer using CustomerCustomizer.
224+
ad_text_asset.text = (
225+
f"Just {{CUSTOMIZER.{customizer_attribute_name}:10USD}}"
226+
)
227+
228+
return ad_text_asset
229+
230+
107231
def create_campaign_budget(client, customer_id):
108232
"""Creates campaign budget resource.
109233
@@ -221,13 +345,17 @@ def create_ad_group(client, customer_id, campaign_resource_name):
221345
return ad_group_resource_name
222346

223347

224-
def create_ad_group_ad(client, customer_id, ad_group_resource_name):
348+
def create_ad_group_ad(
349+
client, customer_id, ad_group_resource_name, customizer_attribute_name
350+
):
225351
"""Creates ad group ad.
226352
227353
Args:
228354
client: an initialized GoogleAdsClient instance.
229355
customer_id: a client customer ID.
230356
ad_group_resource_name: an ad group resource name.
357+
customizer_attribute_name: (optional) the resource name of the customizer attribute
358+
to use in one of the descriptions
231359
232360
Returns:
233361
Ad group ad resource name.
@@ -265,11 +393,17 @@ def create_ad_group_ad(client, customer_id, ad_group_resource_name):
265393
)
266394

267395
# Description 1 and 2
396+
description_1 = create_ad_text_asset(client, "Desc 1 testing")
397+
description_2 = None
398+
if customizer_attribute_name:
399+
description_2 = create_ad_text_asset_with_customizer(
400+
client, customizer_attribute_name
401+
)
402+
else:
403+
description_2 = create_ad_text_asset(client, "Desc 2 testing")
404+
268405
ad_group_ad.ad.responsive_search_ad.descriptions.extend(
269-
[
270-
create_ad_text_asset(client, "Desc 1 testing"),
271-
create_ad_text_asset(client, "Desc 2 testing"),
272-
]
406+
[description_1, description_2]
273407
)
274408

275409
# Paths
@@ -413,11 +547,7 @@ def add_geo_targeting(client, customer_id, campaign_resource_name):
413547
for suggestion in results.geo_target_constant_suggestions:
414548
geo_target_constant = suggestion.geo_target_constant
415549
print(
416-
f"{geo_target_constant.resource_name} "
417-
f"({geo_target_constant.name}, "
418-
f"{geo_target_constant.country_code}, "
419-
f"{geo_target_constant.target_type}, "
420-
f"{geo_target_constant.status.name}) "
550+
f"geo_target_constant: {geo_target_constant} "
421551
f"is found in _LOCALE ({suggestion.locale}) "
422552
f"with reach ({suggestion.reach}) "
423553
f"from search term ({suggestion.search_term})."
@@ -551,10 +681,33 @@ def add_images(client, customer_id, campaign_resource_name):
551681
help="Whether or not the campaign will use image extensions.",
552682
)
553683

684+
# The name of the customizer attribute to be used in the ad customizer, which
685+
# must be unique for a given customer account. To run this example multiple
686+
# times, specify a unique value as a command line argument. Note that there is
687+
# a limit for the number of enabled customizer attributes in one account, so
688+
# you shouldn't run this example more than necessary. For more details visit:
689+
# https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#rules_and_limitations
690+
parser.add_argument(
691+
"-n",
692+
"--customizer_attribute_name",
693+
type=str,
694+
default=None,
695+
help=(
696+
"The name of the customizer attribute to be created. The name must "
697+
"be unique across a single client account, so be sure not to use "
698+
"the same value more than once."
699+
),
700+
)
701+
554702
args = parser.parse_args()
555703

556704
try:
557-
main(googleads_client, args.customer_id)
705+
main(
706+
googleads_client,
707+
args.customer_id,
708+
args.omit_image_extensions,
709+
args.customizer_attribute_name,
710+
)
558711
except GoogleAdsException as ex:
559712
print(
560713
f'Request with ID "{ex.request_id}" failed with status '

0 commit comments

Comments
 (0)