Below you can see code examples showing how to create responsive search ads. As
with other ads, ad creation is accomplished using AdGroupAdService.MutateAdGroupAds
. A ResponsiveSearchAdInfo
requires
at least three headlines, at least two descriptions, and at least one final URL.
Java
This example is not yet available in Java; you can take a look at the other languages.
C#
This example is not yet available in C#; you can take a look at the other languages.
PHP
This example is not yet available in PHP; you can take a look at the other languages.
Python
#!/usr/bin/env python # Copyright 2023 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 # # https://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 shows how to create a complete Responsive Search ad. Includes creation of: budget, campaign, ad group, ad group ad, keywords, and geo targeting. More details on Responsive Search ads can be found here: https://support.google.com/google-ads/answer/7684791 """ import argparse import sys import uuid from typing import List , Optional from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException from google.ads.googleads.v21.common.types.ad_asset import AdTextAsset from google.ads.googleads.v21.enums.types.served_asset_field_type import ( ServedAssetFieldTypeEnum , ) from google.ads.googleads.v21.resources.types.ad_group import AdGroup from google.ads.googleads.v21.resources.types.ad_group_ad import AdGroupAd from google.ads.googleads.v21.resources.types.ad_group_criterion import ( AdGroupCriterion , ) from google.ads.googleads.v21.resources.types.campaign import Campaign from google.ads.googleads.v21.resources.types.campaign_budget import ( CampaignBudget , ) from google.ads.googleads.v21.resources.types.campaign_criterion import ( CampaignCriterion , ) from google.ads.googleads.v21.resources.types.customer_customizer import ( CustomerCustomizer , ) from google.ads.googleads.v21.resources.types.customizer_attribute import ( CustomizerAttribute , ) from google.ads.googleads.v21.services.services.ad_group_ad_service import ( AdGroupAdServiceClient , ) from google.ads.googleads.v21.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient , ) from google.ads.googleads.v21.services.services.ad_group_service import ( AdGroupServiceClient , ) from google.ads.googleads.v21.services.services.campaign_budget_service import ( CampaignBudgetServiceClient , ) from google.ads.googleads.v21.services.services.campaign_criterion_service import ( CampaignCriterionServiceClient , ) from google.ads.googleads.v21.services.services.campaign_service import ( CampaignServiceClient , ) from google.ads.googleads.v21.services.services.customer_customizer_service import ( CustomerCustomizerServiceClient , ) from google.ads.googleads.v21.services.services.customizer_attribute_service import ( CustomizerAttributeServiceClient , ) from google.ads.googleads.v21.services.services.geo_target_constant_service import ( GeoTargetConstantServiceClient , ) from google.ads.googleads.v21.services.types.geo_target_constant_service import ( SuggestGeoTargetConstantsRequest , SuggestGeoTargetConstantsResponse , ) from google.ads.googleads.v21.services.types.ad_group_ad_service import ( AdGroupAdOperation , MutateAdGroupAdsResponse , ) from google.ads.googleads.v21.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation , MutateAdGroupCriteriaResponse , ) from google.ads.googleads.v21.services.types.ad_group_service import ( AdGroupOperation , MutateAdGroupsResponse , ) from google.ads.googleads.v21.services.types.campaign_budget_service import ( CampaignBudgetOperation , MutateCampaignBudgetsResponse , ) from google.ads.googleads.v21.services.types.campaign_criterion_service import ( CampaignCriterionOperation , MutateCampaignCriteriaResponse , ) from google.ads.googleads.v21.services.types.campaign_service import ( CampaignOperation , MutateCampaignsResponse , ) from google.ads.googleads.v21.services.types.customer_customizer_service import ( CustomerCustomizerOperation , MutateCustomerCustomizersResponse , ) from google.ads.googleads.v21.services.types.customizer_attribute_service import ( CustomizerAttributeOperation , MutateCustomizerAttributesResponse , ) # Keywords from user. KEYWORD_TEXT_EXACT = "example of exact match" KEYWORD_TEXT_PHRASE = "example of phrase match" KEYWORD_TEXT_BROAD = "example of broad match" # Geo targeting from user. GEO_LOCATION_1 = "Buenos aires" GEO_LOCATION_2 = "San Isidro" GEO_LOCATION_3 = "Mar del Plata" # LOCALE and COUNTRY_CODE are used for geo targeting. # LOCALE is using ISO 639-1 format. If an invalid LOCALE is given, # 'es' is used by default. LOCALE = "es" # A list of country codes can be referenced here: # https://developers.google.com/google-ads/api/reference/data/geotargets COUNTRY_CODE = "AR" def main ( client : GoogleAdsClient , customer_id : str , customizer_attribute_name : Optional [ str ] = None , ) - > None : """ The main method that creates all necessary entities for the example. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. customizer_attribute_name: The name of the customizer attribute to be created """ if customizer_attribute_name : customizer_attribute_resource_name : str = create_customizer_attribute ( client , customer_id , customizer_attribute_name ) link_customizer_attribute_to_customer ( client , customer_id , customizer_attribute_resource_name ) # Create a budget, which can be shared by multiple campaigns. campaign_budget : str = create_campaign_budget ( client , customer_id ) campaign_resource_name : str = create_campaign ( client , customer_id , campaign_budget ) ad_group_resource_name : str = create_ad_group ( client , customer_id , campaign_resource_name ) create_ad_group_ad ( client , customer_id , ad_group_resource_name , customizer_attribute_name ) add_keywords ( client , customer_id , ad_group_resource_name ) add_geo_targeting ( client , customer_id , campaign_resource_name ) def create_customizer_attribute ( client : GoogleAdsClient , customer_id : str , customizer_attribute_name : str ) - > str : """Creates a customizer attribute with the given customizer attribute name. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. customizer_attribute_name: the name for the customizer attribute. Returns: A resource name for a customizer attribute. """ # Create a customizer attribute operation for creating a customizer # attribute. operation : CustomizerAttributeOperation = client . get_type ( "CustomizerAttributeOperation" ) # Create a customizer attribute with the specified name. customizer_attribute : CustomizerAttribute = operation . create customizer_attribute . name = customizer_attribute_name # Specify the type to be 'PRICE' so that we can dynamically customize the # part of the ad's description that is a price of a product/service we # advertise. customizer_attribute . type_ = client . enums . CustomizerAttributeTypeEnum . PRICE # Issue a mutate request to add the customizer attribute and prints its # information. customizer_attribute_service : CustomizerAttributeServiceClient = ( client . get_service ( "CustomizerAttributeService" ) ) response : MutateCustomizerAttributesResponse = ( customizer_attribute_service . mutate_customizer_attributes ( customer_id = customer_id , operations = [ operation ] ) ) resource_name : str = response . results [ 0 ] . resource_name print ( f "Added a customizer attribute with resource name: ' { resource_name } '" ) return resource_name def link_customizer_attribute_to_customer ( client : GoogleAdsClient , customer_id : str , customizer_attribute_resource_name : str , ) - > None : """Links the customizer attribute to the customer. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. customizer_attribute_resource_name: a resource name for customizer attribute. """ # Create a customer customizer operation. operation : CustomerCustomizerOperation = client . get_type ( "CustomerCustomizerOperation" ) # Create a customer customizer with the value to be used in the responsive # search ad. customer_customizer : CustomerCustomizer = operation . create customer_customizer . customizer_attribute = ( customizer_attribute_resource_name ) customer_customizer . value . type_ = ( client . enums . CustomizerAttributeTypeEnum . PRICE ) # The ad customizer will dynamically replace the placeholder with this value # when the ad serves. customer_customizer . value . string_value = "100USD" customer_customizer_service : CustomerCustomizerServiceClient = ( client . get_service ( "CustomerCustomizerService" ) ) # Issue a mutate request to create the customer customizer and prints its # information. response : MutateCustomerCustomizersResponse = ( customer_customizer_service . mutate_customer_customizers ( customer_id = customer_id , operations = [ operation ] ) ) resource_name : str = response . results [ 0 ] . resource_name print ( f "Added a customer customizer to the customer with resource name: ' { resource_name } '" ) def create_ad_text_asset ( client : GoogleAdsClient , text : str , pinned_field : Optional [ ServedAssetFieldTypeEnum . ServedAssetFieldType ] = None , ) - > AdTextAsset : """Create an AdTextAsset. Args: client: an initialized GoogleAdsClient instance. text: text for headlines and descriptions. pinned_field: to pin a text asset so it always shows in the ad. Returns: An AdTextAsset. """ ad_text_asset : AdTextAsset = client . get_type ( "AdTextAsset" ) ad_text_asset . text = text if pinned_field : ad_text_asset . pinned_field = pinned_field return ad_text_asset def create_ad_text_asset_with_customizer ( client : GoogleAdsClient , customizer_attribute_resource_name : str ) - > AdTextAsset : """Create an AdTextAsset. Args: client: an initialized GoogleAdsClient instance. customizer_attribute_resource_name: The resource name of the customizer attribute. Returns: An AdTextAsset. """ ad_text_asset : AdTextAsset = client . get_type ( "AdTextAsset" ) # Create this particular description using the ad customizer. Visit # https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#ad_customizers_in_responsive_search_ads # for details about the placeholder format. The ad customizer replaces the # placeholder with the value we previously created and linked to the # customer using CustomerCustomizer. ad_text_asset . text = ( f "Just {{CUSTOMIZER.{customizer_attribute_resource_name}:10USD} } " ) return ad_text_asset def create_campaign_budget ( client : GoogleAdsClient , customer_id : str ) - > str : """Creates campaign budget resource. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. Returns: Campaign budget resource name. """ # Create a budget, which can be shared by multiple campaigns. campaign_budget_service : CampaignBudgetServiceClient = client . get_service ( "CampaignBudgetService" ) campaign_budget_operation : CampaignBudgetOperation = client . get_type ( "CampaignBudgetOperation" ) campaign_budget : CampaignBudget = campaign_budget_operation . create campaign_budget . name = f "Campaign budget { uuid . uuid4 () } " campaign_budget . delivery_method = ( client . enums . BudgetDeliveryMethodEnum . STANDARD ) campaign_budget . amount_micros = 500000 # Add budget. campaign_budget_response : MutateCampaignBudgetsResponse = ( campaign_budget_service . mutate_campaign_budgets ( customer_id = customer_id , operations = [ campaign_budget_operation ] ) ) return campaign_budget_response . results [ 0 ] . resource_name def create_campaign ( client : GoogleAdsClient , customer_id : str , campaign_budget : str ) - > str : """Creates campaign resource. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. campaign_budget: a budget resource name. Returns: Campaign resource name. """ campaign_service : CampaignServiceClient = client . get_service ( "CampaignService" ) campaign_operation : CampaignOperation = client . get_type ( "CampaignOperation" ) campaign : Campaign = campaign_operation . create campaign . name = f "Testing RSA via API { uuid . uuid4 () } " campaign . advertising_channel_type = ( client . enums . AdvertisingChannelTypeEnum . SEARCH ) # 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. campaign . status = client . enums . CampaignStatusEnum . PAUSED # Set the bidding strategy and budget. # The bidding strategy for Maximize Clicks is TargetSpend. # The target_spend_micros is deprecated so don't put any value. # See other bidding strategies you can select in the link below. # https://developers.google.com/google-ads/api/reference/rpc/latest/Campaign#campaign_bidding_strategy campaign . target_spend . target_spend_micros = 0 campaign . campaign_budget = campaign_budget # Set the campaign network options. campaign . network_settings . target_google_search = True campaign . network_settings . target_search_network = True campaign . network_settings . target_partner_search_network = False # Enable Display Expansion on Search campaigns. For more details see: # https://support.google.com/google-ads/answer/7193800 campaign . network_settings . target_content_network = True # # Optional: Set the start date. # start_time = datetime.date.today() + datetime.timedelta(days=1) # campaign.start_date = datetime.date.strftime(start_time, _DATE_FORMAT) # # Optional: Set the end date. # end_time = start_time + datetime.timedelta(weeks=4) # campaign.end_date = datetime.date.strftime(end_time, _DATE_FORMAT) # Add the campaign. campaign_response : MutateCampaignsResponse = ( campaign_service . mutate_campaigns ( customer_id = customer_id , operations = [ campaign_operation ] ) ) resource_name : str = campaign_response . results [ 0 ] . resource_name print ( f "Created campaign { resource_name } ." ) return resource_name def create_ad_group ( client : GoogleAdsClient , customer_id : str , campaign_resource_name : str , ) - > str : """Creates ad group. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. campaign_resource_name: a campaign resource name. Returns: Ad group ID. """ ad_group_service : AdGroupServiceClient = client . get_service ( "AdGroupService" ) ad_group_operation : AdGroupOperation = client . get_type ( "AdGroupOperation" ) ad_group : AdGroup = ad_group_operation . create ad_group . name = f "Testing RSA via API { uuid . uuid4 () } " ad_group . status = client . enums . AdGroupStatusEnum . ENABLED ad_group . campaign = campaign_resource_name ad_group . type_ = client . enums . AdGroupTypeEnum . SEARCH_STANDARD # If you want to set up a max CPC bid uncomment line below. # ad_group.cpc_bid_micros = 10000000 # Add the ad group. ad_group_response : MutateAdGroupsResponse = ( ad_group_service . mutate_ad_groups ( customer_id = customer_id , operations = [ ad_group_operation ] ) ) ad_group_resource_name : str = ad_group_response . results [ 0 ] . resource_name print ( f "Created ad group { ad_group_resource_name } ." ) return ad_group_resource_name def create_ad_group_ad ( client : GoogleAdsClient , customer_id : str , ad_group_resource_name : str , customizer_attribute_name : Optional [ str ], ) - > None : """Creates ad group ad. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. ad_group_resource_name: an ad group resource name. customizer_attribute_name: (optional) If present, indicates the resource name of the customizer attribute to use in one of the descriptions Returns: None. """ ad_group_ad_service : AdGroupAdServiceClient = client . get_service ( "AdGroupAdService" ) ad_group_ad_operation : AdGroupAdOperation = client . get_type ( "AdGroupAdOperation" ) ad_group_ad : AdGroupAd = ad_group_ad_operation . create ad_group_ad . status = client . enums . AdGroupAdStatusEnum . ENABLED ad_group_ad . ad_group = ad_group_resource_name # Set responsive search ad info. # https://developers.google.com/google-ads/api/reference/rpc/latest/ResponsiveSearchAdInfo # The list of possible final URLs after all cross-domain redirects for the ad. ad_group_ad . ad . final_urls . append ( "https://www.example.com/" ) # Set a pinning to always choose this asset for HEADLINE_1. Pinning is # optional; if no pinning is set, then headlines and descriptions will be # rotated and the ones that perform best will be used more often. # Headline 1 served_asset_enum : ServedAssetFieldTypeEnum = ( client . enums . ServedAssetFieldTypeEnum ) pinned_headline : AdTextAsset = create_ad_text_asset ( client , "Headline 1 testing" , served_asset_enum ) # Headline 2 and 3 ad_group_ad . ad . responsive_search_ad . headlines . extend ( [ pinned_headline , create_ad_text_asset ( client , "Headline 2 testing" ), create_ad_text_asset ( client , "Headline 3 testing" ), ] ) # Description 1 and 2 description_1 : AdTextAsset = create_ad_text_asset ( client , "Desc 1 testing" ) description_2 : Optional [ AdTextAsset ] = None if customizer_attribute_name : description_2 = create_ad_text_asset_with_customizer ( client , customizer_attribute_name ) else : description_2 = create_ad_text_asset ( client , "Desc 2 testing" ) ad_group_ad . ad . responsive_search_ad . descriptions . extend ( [ description_1 , description_2 ] ) # Paths # First and second part of text that can be appended to the URL in the ad. # If you use the examples below, the ad will show # https://www.example.com/all-inclusive/deals ad_group_ad . ad . responsive_search_ad . path1 = "all-inclusive" ad_group_ad . ad . responsive_search_ad . path2 = "deals" # Send a request to the server to add a responsive search ad. ad_group_ad_response : MutateAdGroupAdsResponse = ( ad_group_ad_service . mutate_ad_group_ads ( customer_id = customer_id , operations = [ ad_group_ad_operation ] ) ) for result in ad_group_ad_response . results : print ( f "Created responsive search ad with resource name " f '" { result . resource_name } ".' ) def add_keywords ( client : GoogleAdsClient , customer_id : str , ad_group_resource_name : str ) - > None : """Creates keywords. Creates 3 keyword match types: EXACT, PHRASE, and BROAD. EXACT: ads may show on searches that ARE the same meaning as your keyword. PHRASE: ads may show on searches that INCLUDE the meaning of your keyword. BROAD: ads may show on searches that RELATE to your keyword. For smart bidding, BROAD is the recommended one. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. ad_group_resource_name: an ad group resource name. """ ad_group_criterion_service : AdGroupCriterionServiceClient = ( client . get_service ( "AdGroupCriterionService" ) ) operations : List [ AdGroupCriterionOperation ] = [] # Create keyword 1. ad_group_criterion_operation : AdGroupCriterionOperation = client . get_type ( "AdGroupCriterionOperation" ) ad_group_criterion : AdGroupCriterion = ad_group_criterion_operation . create ad_group_criterion . ad_group = ad_group_resource_name ad_group_criterion . status = client . enums . AdGroupCriterionStatusEnum . ENABLED ad_group_criterion . keyword . text = KEYWORD_TEXT_EXACT ad_group_criterion . keyword . match_type = ( client . enums . KeywordMatchTypeEnum . EXACT ) # Uncomment the below line if you want to change this keyword to a negative target. # ad_group_criterion.negative = True # Optional repeated field # ad_group_criterion.final_urls.append('https://www.example.com') # Add operation operations . append ( ad_group_criterion_operation ) # Create keyword 2. ad_group_criterion_operation : AdGroupCriterionOperation = client . get_type ( "AdGroupCriterionOperation" ) ad_group_criterion : AdGroupCriterion = ad_group_criterion_operation . create ad_group_criterion . ad_group = ad_group_resource_name ad_group_criterion . status = client . enums . AdGroupCriterionStatusEnum . ENABLED ad_group_criterion . keyword . text = KEYWORD_TEXT_PHRASE ad_group_criterion . keyword . match_type = ( client . enums . KeywordMatchTypeEnum . PHRASE ) # Uncomment the below line if you want to change this keyword to a negative target. # ad_group_criterion.negative = True # Optional repeated field # ad_group_criterion.final_urls.append('https://www.example.com') # Add operation operations . append ( ad_group_criterion_operation ) # Create keyword 3. ad_group_criterion_operation : AdGroupCriterionOperation = client . get_type ( "AdGroupCriterionOperation" ) ad_group_criterion : AdGroupCriterion = ad_group_criterion_operation . create ad_group_criterion . ad_group = ad_group_resource_name ad_group_criterion . status = client . enums . AdGroupCriterionStatusEnum . ENABLED ad_group_criterion . keyword . text = KEYWORD_TEXT_BROAD ad_group_criterion . keyword . match_type = ( client . enums . KeywordMatchTypeEnum . BROAD ) # Uncomment the below line if you want to change this keyword to a negative target. # ad_group_criterion.negative = True # Optional repeated field # ad_group_criterion.final_urls.append('https://www.example.com') # Add operation operations . append ( ad_group_criterion_operation ) # Add keywords ad_group_criterion_response : MutateAdGroupCriteriaResponse = ( ad_group_criterion_service . mutate_ad_group_criteria ( customer_id = customer_id , operations = operations , ) ) for result in ad_group_criterion_response . results : print ( "Created keyword " f " { result . resource_name } ." ) def add_geo_targeting ( client : GoogleAdsClient , customer_id : str , campaign_resource_name : str ) - > None : """Creates geo targets. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. campaign_resource_name: an campaign resource name. Returns: None. """ geo_target_constant_service : GeoTargetConstantServiceClient = ( client . get_service ( "GeoTargetConstantService" ) ) # Search by location names from # GeoTargetConstantService.suggest_geo_target_constants() and directly # apply GeoTargetConstant.resource_name. gtc_request : SuggestGeoTargetConstantsRequest = client . get_type ( "SuggestGeoTargetConstantsRequest" ) gtc_request . locale = LOCALE gtc_request . country_code = COUNTRY_CODE # The location names to get suggested geo target constants. gtc_request . location_names . names . extend ( [ GEO_LOCATION_1 , GEO_LOCATION_2 , GEO_LOCATION_3 ] ) results : SuggestGeoTargetConstantsResponse = ( geo_target_constant_service . suggest_geo_target_constants ( gtc_request ) ) operations : List [ CampaignCriterionOperation ] = [] for suggestion in results . geo_target_constant_suggestions : print ( "geo_target_constant: " f " { suggestion . geo_target_constant . resource_name } " f "is found in LOCALE ( { suggestion . locale } ) " f "with reach ( { suggestion . reach } ) " f "from search term ( { suggestion . search_term } )." ) # Create the campaign criterion for location targeting. campaign_criterion_operation : CampaignCriterionOperation = ( client . get_type ( "CampaignCriterionOperation" ) ) campaign_criterion : CampaignCriterion = ( campaign_criterion_operation . create ) campaign_criterion . campaign = campaign_resource_name campaign_criterion . location . geo_target_constant = ( suggestion . geo_target_constant . resource_name ) operations . append ( campaign_criterion_operation ) campaign_criterion_service : CampaignCriterionServiceClient = ( client . get_service ( "CampaignCriterionService" ) ) campaign_criterion_response : MutateCampaignCriteriaResponse = ( campaign_criterion_service . mutate_campaign_criteria ( customer_id = customer_id , operations = [ * operations ] ) ) for result in campaign_criterion_response . results : print ( f 'Added campaign criterion " { result . resource_name } ".' ) if __name__ == "__main__" : parser : argparse . ArgumentParser = argparse . ArgumentParser ( description = ( "Creates a Responsive Search Ad for specified customer." ) ) # The following argument(s) should be provided to run the example. parser . add_argument ( "-c" , "--customer_id" , type = str , required = True , help = "The Google Ads customer ID." , ) # The name of the customizer attribute used in the ad customizer, which # must be unique for a given customer account. To run this example multiple # times, specify a unique value as a command line argument. Note that there is # a limit for the number of enabled customizer attributes in one account # For more details visit: # https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#rules_and_limitations parser . add_argument ( "-n" , "--customizer_attribute_name" , type = str , default = None , help = ( "The name of the customizer attribute to be created. The name must " "be unique across a client account, so be sure not to use " "the same value more than once." ), ) args : argparse . Namespace = parser . parse_args () # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client : GoogleAdsClient = GoogleAdsClient . load_from_storage ( version = "v21" ) try : main ( googleads_client , args . customer_id , args . customizer_attribute_name , ) except GoogleAdsException as ex : print ( f 'Request with ID " { ex . request_id } " failed with status ' f '" { ex . error . code () . name } " and includes the following errors:' ) for error in ex . failure . errors : print ( f 'Error with message " { error . message } ".' ) if error . location : for field_path_element in error . location . field_path_elements : print ( f " \t\t On field: { field_path_element . field_name } " ) sys . exit ( 1 )
Ruby
This example is not yet available in Ruby; you can take a look at the other languages.
Perl
This example is not yet available in Perl; you can take a look at the other languages.