2525import argparse
2626import sys
2727import uuid
28+
2829import requests
2930
3031from google .ads .googleads .client import GoogleAdsClient
3132from 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"
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+
107231def 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