Add Smart Campaign

Java

 // Copyright 2021 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. 
 package 
  
 com.google.ads.googleads.examples.advancedoperations 
 ; 
 import static 
  
 com.google.ads.googleads.v21.enums.EuPoliticalAdvertisingStatusEnum.EuPoliticalAdvertisingStatus.DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING 
 ; 
 import 
  
 com.beust.jcommander.Parameter 
 ; 
 import 
  
 com.google.ads.googleads.examples.utils.ArgumentNames 
 ; 
 import 
  
 com.google.ads.googleads.examples.utils.CodeSampleHelper 
 ; 
 import 
  
 com.google.ads.googleads.examples.utils.CodeSampleParams 
 ; 
 import 
  
 com.google.ads.googleads.lib.GoogleAdsClient 
 ; 
 import 
  
 com.google.ads.googleads.lib.utils.FieldMasks 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.AdScheduleInfo 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.AdTextAsset 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.KeywordThemeInfo 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.LocationInfo 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.SmartCampaignAdInfo 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.AdGroupTypeEnum.AdGroupType 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.AdTypeEnum.AdType 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.AdvertisingChannelSubTypeEnum.AdvertisingChannelSubType 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.AdvertisingChannelTypeEnum.AdvertisingChannelType 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.BudgetDeliveryMethodEnum.BudgetDeliveryMethod 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.BudgetTypeEnum.BudgetType 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.CampaignStatusEnum.CampaignStatus 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.DayOfWeekEnum.DayOfWeek 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.MinuteOfHourEnum.MinuteOfHour 
 ; 
 import 
  
 com.google.ads.googleads.v21.errors.GoogleAdsError 
 ; 
 import 
  
 com.google.ads.googleads.v21.errors.GoogleAdsException 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.Ad 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.SmartCampaignSetting 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.GoogleAdsServiceClient 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.KeywordThemeConstantServiceClient 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.MutateGoogleAdsResponse 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.MutateOperation 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.MutateOperationResponse 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SmartCampaignSuggestServiceClient 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SmartCampaignSuggestionInfo 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SmartCampaignSuggestionInfo.BusinessContext 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SmartCampaignSuggestionInfo.LocationList 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestKeywordThemeConstantsRequest 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestKeywordThemeConstantsResponse 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestKeywordThemesRequest 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestKeywordThemesResponse 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestKeywordThemesResponse.KeywordTheme 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestSmartCampaignAdRequest 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestSmartCampaignAdResponse 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestSmartCampaignBudgetOptionsRequest 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestSmartCampaignBudgetOptionsResponse 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SuggestSmartCampaignBudgetOptionsResponse.BudgetOption 
 ; 
 import 
  
 com.google.ads.googleads.v21.utils.ResourceNames 
 ; 
 import 
  
 com.google.protobuf.Descriptors.OneofDescriptor 
 ; 
 import 
  
 com.google.protobuf.Message 
 ; 
 import 
  
 java.io.FileNotFoundException 
 ; 
 import 
  
 java.io.IOException 
 ; 
 import 
  
 java.util.ArrayList 
 ; 
 import 
  
 java.util.Arrays 
 ; 
 import 
  
 java.util.Collection 
 ; 
 import 
  
 java.util.List 
 ; 
 import 
  
 java.util.stream.Collectors 
 ; 
 import 
  
 java.util.stream.Stream 
 ; 
 /** Demonstrates how to create a Smart Campaign. */ 
 public 
  
 class 
 AddSmartCampaign 
  
 { 
  
 private 
  
 static 
  
 final 
  
 long 
  
 GEO_TARGET_CONSTANT 
  
 = 
  
 1023191 
 ; 
  
 private 
  
 static 
  
 final 
  
 String 
  
 COUNTRY_CODE 
  
 = 
  
 "US" 
 ; 
  
 private 
  
 static 
  
 final 
  
 String 
  
 LANGUAGE_CODE 
  
 = 
  
 "en" 
 ; 
  
 private 
  
 static 
  
 final 
  
 String 
  
 LANDING_PAGE_URL 
  
 = 
  
 "http://www.example.com" 
 ; 
  
 private 
  
 static 
  
 final 
  
 String 
  
 PHONE_NUMBER 
  
 = 
  
 "800-555-0100" 
 ; 
  
 private 
  
 static 
  
 final 
  
 long 
  
 BUDGET_TEMPORARY_ID 
  
 = 
  
 - 
 1 
 ; 
  
 private 
  
 static 
  
 final 
  
 long 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
  
 = 
  
 - 
 2 
 ; 
  
 private 
  
 static 
  
 final 
  
 long 
  
 AD_GROUP_TEMPORARY_ID 
  
 = 
  
 - 
 3 
 ; 
  
 private 
  
 static 
  
 final 
  
 int 
  
 NUM_REQUIRED_HEADLINES 
  
 = 
  
 3 
 ; 
  
 private 
  
 static 
  
 final 
  
 int 
  
 NUM_REQUIRED_DESCRIPTIONS 
  
 = 
  
 2 
 ; 
  
 private 
  
 static 
  
 class 
 AddSmartCampaignParams 
  
 extends 
  
 CodeSampleParams 
  
 { 
  
 @Parameter 
 ( 
  
 names 
  
 = 
  
 ArgumentNames 
 . 
 CUSTOMER_ID 
 , 
  
 description 
  
 = 
  
 "The Google Ads customer ID" 
 , 
  
 required 
  
 = 
  
 true 
 ) 
  
 private 
  
 long 
  
 customerId 
 ; 
  
 @Parameter 
 ( 
  
 names 
  
 = 
  
 ArgumentNames 
 . 
 KEYWORD_TEXT 
 , 
  
 description 
  
 = 
  
 "A keyword text used to retrieve keyword theme constant suggestions from the" 
  
 + 
  
 " KeywordThemeConstantService. These keyword theme suggestions are generated" 
  
 + 
  
 " using auto-completion data for the given text and may help improve the" 
  
 + 
  
 " performance of the Smart campaign." 
 ) 
  
 private 
  
 String 
  
 keywordText 
 ; 
  
 @Parameter 
 ( 
  
 names 
  
 = 
  
 ArgumentNames 
 . 
 FREE_FORM_KEYWORD_TEXT 
 , 
  
 description 
  
 = 
  
 "A keyword text used to create a freeForm keyword theme, which is entirely" 
  
 + 
  
 " user-specified and not derived from any suggestion service. Using free-form" 
  
 + 
  
 " keyword themes is typically not recommended because they are less effective" 
  
 + 
  
 " than suggested keyword themes, however they are useful in situations where a" 
  
 + 
  
 " very specific term needs to be targeted." 
 ) 
  
 private 
  
 String 
  
 freeFormKeywordText 
 ; 
  
 @Parameter 
 ( 
  
 names 
  
 = 
  
 ArgumentNames 
 . 
 BUSINESS_PROFILE_LOCATION 
 , 
  
 description 
  
 = 
  
 "The resource name of a Business Profile location. This is required if a business name" 
  
 + 
  
 " is not provided. It can be retrieved using the Business Profile API" 
  
 + 
  
 " (https://developers.google.com/my-business/reference/businessinformation/rest/v1/accounts.locations)" 
  
 + 
  
 " or from the Business Profile UI" 
  
 + 
  
 " (https://support.google.com/business/answer/10737668" 
 ) 
  
 private 
  
 String 
  
 businessProfileLocation 
 ; 
  
 @Parameter 
 ( 
  
 names 
  
 = 
  
 ArgumentNames 
 . 
 BUSINESS_NAME 
 , 
  
 description 
  
 = 
  
 "The name of a Business Profile business. This is required if a business" 
  
 + 
  
 " location ID is not provided." 
 ) 
  
 private 
  
 String 
  
 businessName 
 ; 
  
 } 
  
 public 
  
 static 
  
 void 
  
 main 
 ( 
 String 
 [] 
  
 args 
 ) 
  
 throws 
  
 IOException 
  
 { 
  
 AddSmartCampaignParams 
  
 params 
  
 = 
  
 new 
  
 AddSmartCampaignParams 
 (); 
  
 if 
  
 ( 
 ! 
 params 
 . 
 parseArguments 
 ( 
 args 
 )) 
  
 { 
  
 // Either pass the required parameters for this example on the command line, or insert them 
  
 // into the code here. See the parameter class definition above for descriptions. 
  
 params 
 . 
 customerId 
  
 = 
  
 Long 
 . 
 parseLong 
 ( 
 "INSERT_CUSTOMER_ID_HERE" 
 ); 
  
 // Optionally specifies a seed keyword. 
  
 params 
 . 
 keywordText 
  
 = 
  
 null 
 ; 
  
 // Optionally specifies a keyword that should be included as-is. 
  
 params 
 . 
 freeFormKeywordText 
  
 = 
  
 null 
 ; 
  
 // Must specify one of business profile location or business name. 
  
 params 
 . 
 businessProfileLocation 
  
 = 
  
 "INSERT_BUSINESS_PROFILE_LOCATION_HERE" 
 ; 
  
 params 
 . 
 businessName 
  
 = 
  
 "INSERT_BUSINESS_NAME" 
 ; 
  
 } 
  
 GoogleAdsClient 
  
 googleAdsClient 
  
 = 
  
 null 
 ; 
  
 try 
  
 { 
  
 googleAdsClient 
  
 = 
  
 GoogleAdsClient 
 . 
 newBuilder 
 (). 
 fromPropertiesFile 
 (). 
 build 
 (); 
  
 } 
  
 catch 
  
 ( 
 FileNotFoundException 
  
 fnfe 
 ) 
  
 { 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
  
 "Failed to load GoogleAdsClient configuration from file. Exception: %s%n" 
 , 
  
 fnfe 
 ); 
  
 System 
 . 
 exit 
 ( 
 1 
 ); 
  
 } 
  
 catch 
  
 ( 
 IOException 
  
 ioe 
 ) 
  
 { 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
 "Failed to create GoogleAdsClient. Exception: %s%n" 
 , 
  
 ioe 
 ); 
  
 System 
 . 
 exit 
 ( 
 1 
 ); 
  
 } 
  
 try 
  
 { 
  
 new 
  
 AddSmartCampaign 
 () 
  
 . 
 runExample 
 ( 
  
 googleAdsClient 
 , 
  
 params 
 . 
 customerId 
 , 
  
 params 
 . 
 keywordText 
 , 
  
 params 
 . 
 freeFormKeywordText 
 , 
  
 params 
 . 
 businessProfileLocation 
 , 
  
 params 
 . 
 businessName 
 ); 
  
 } 
  
 catch 
  
 ( 
 GoogleAdsException 
  
 gae 
 ) 
  
 { 
  
 // GoogleAdsException is the base class for most exceptions thrown by an API request. 
  
 // Instances of this exception have a message and a GoogleAdsFailure that contains a 
  
 // collection of GoogleAdsErrors that indicate the underlying causes of the 
  
 // GoogleAdsException. 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
  
 "Request ID %s failed due to GoogleAdsException. Underlying errors:%n" 
 , 
  
 gae 
 . 
 getRequestId 
 ()); 
  
 int 
  
 i 
  
 = 
  
 0 
 ; 
  
 for 
  
 ( 
 GoogleAdsError 
  
 googleAdsError 
  
 : 
  
 gae 
 . 
 getGoogleAdsFailure 
 (). 
 getErrorsList 
 ()) 
  
 { 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
 "  Error %d: %s%n" 
 , 
  
 i 
 ++ 
 , 
  
 googleAdsError 
 ); 
  
 } 
  
 System 
 . 
 exit 
 ( 
 1 
 ); 
  
 } 
  
 } 
  
 private 
  
 void 
  
 runExample 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long 
  
 customerId 
 , 
  
 String 
  
 keywordText 
 , 
  
 String 
  
 freeFormKeywordText 
 , 
  
 String 
  
 businessProfileLocation 
 , 
  
 String 
  
 businessName 
 ) 
  
 { 
  
 // Checks that exactly one of businessProfileLocation and businessName is set. 
  
 if 
  
 ( 
 businessProfileLocation 
  
 != 
  
 null 
 && 
 businessName 
  
 != 
  
 null 
 ) 
  
 { 
  
 throw 
  
 new 
  
 IllegalArgumentException 
 ( 
  
 "Both the business location resource name and business name are provided but they are" 
  
 + 
  
 " mutually exclusive. Please only set a value for one of them." 
 ); 
  
 } 
  
 if 
  
 ( 
 businessProfileLocation 
  
 == 
  
 null 
 && 
 businessName 
  
 == 
  
 null 
 ) 
  
 { 
  
 throw 
  
 new 
  
 IllegalArgumentException 
 ( 
  
 "Neither the business location resource name nor the business name are provided. Please" 
  
 + 
  
 " set a value for one of them." 
 ); 
  
 } 
  
 // Gets the SmartCampaignSuggestionInfo object which acts as the basis for many of the 
  
 // entities necessary to create a Smart campaign. It will be reused a number of times to 
  
 // retrieve suggestions for keyword themes, budget amount, ad creatives, and campaign criteria. 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
  
 = 
  
 getSmartCampaignSuggestionInfo 
 ( 
 googleAdsClient 
 , 
  
 businessProfileLocation 
 , 
  
 businessName 
 ); 
  
 // Generates a list of keyword themes using the SuggestKeywordThemes method on the 
  
 // SmartCampaignSuggestService. It is strongly recommended that you use this strategy for 
  
 // generating keyword themes. 
  
 List<KeywordTheme> 
  
 keywordThemes 
  
 = 
  
 getKeywordThemeSuggestions 
 ( 
 googleAdsClient 
 , 
  
 customerId 
 , 
  
 suggestionInfo 
 ); 
  
 // If a keyword text is given, retrieves keyword theme constant suggestions from the 
  
 // KeywordThemeConstantService, maps them to KeywordThemes, and appends them to the existing 
  
 // list. 
  
 // This logic should ideally only be used if the suggestions from the 
  
 // getKeywordThemeSuggestions function are insufficient. 
  
 if 
  
 ( 
 keywordText 
  
 != 
  
 null 
 ) 
  
 { 
  
 keywordThemes 
 . 
 addAll 
 ( 
 getKeywordTextAutoCompletions 
 ( 
 googleAdsClient 
 , 
  
 keywordText 
 )); 
  
 } 
  
 // Converts the list of KeywordThemes to a list of KeywordThemes objects. 
  
 List<KeywordThemeInfo> 
  
 keywordThemeInfos 
  
 = 
  
 getKeywordThemeInfos 
 ( 
 keywordThemes 
 ); 
  
 // Optionally includes any freeForm keywords in verbatim. 
  
 if 
  
 ( 
 freeFormKeywordText 
  
 != 
  
 null 
 ) 
  
 { 
  
 keywordThemeInfos 
 . 
 add 
 ( 
  
 KeywordThemeInfo 
 . 
 newBuilder 
 (). 
 setFreeFormKeywordTheme 
 ( 
 freeFormKeywordText 
 ). 
 build 
 ()); 
  
 } 
  
 // Includes the keyword suggestions in the overall SuggestionInfo object. 
  
 suggestionInfo 
  
 = 
  
 suggestionInfo 
 . 
 toBuilder 
 (). 
 addAllKeywordThemes 
 ( 
 keywordThemeInfos 
 ). 
 build 
 (); 
  
 // Generates a suggested daily budget. 
  
 long 
  
 suggestedDailyBudgetMicros 
  
 = 
  
 getBudgetSuggestions 
 ( 
 googleAdsClient 
 , 
  
 customerId 
 , 
  
 suggestionInfo 
 ); 
  
 // Creates adSuggestions. 
  
 SmartCampaignAdInfo 
  
 adSuggestions 
  
 = 
  
 getAdSuggestions 
 ( 
 googleAdsClient 
 , 
  
 customerId 
 , 
  
 suggestionInfo 
 ); 
  
 // Creates an array of operations which will create the campaign and related entities. 
  
 List<MutateOperation> 
  
 operations 
  
 = 
  
 new 
  
 ArrayList 
 ( 
  
 Arrays 
 . 
 asList 
 ( 
  
 createCampaignBudgetOperation 
 ( 
 customerId 
 , 
  
 suggestedDailyBudgetMicros 
 ), 
  
 createSmartCampaignOperation 
 ( 
 customerId 
 ), 
  
 createSmartCampaignSettingOperation 
 ( 
  
 customerId 
 , 
  
 businessProfileLocation 
 , 
  
 businessName 
 ), 
  
 createAdGroupOperation 
 ( 
 customerId 
 ), 
  
 createAdGroupAdOperation 
 ( 
 customerId 
 , 
  
 adSuggestions 
 ))); 
  
 operations 
 . 
 addAll 
 ( 
  
 createCampaignCriterionOperations 
 ( 
 customerId 
 , 
  
 keywordThemeInfos 
 , 
  
 suggestionInfo 
 )); 
  
 // Issues a mutate request to add the various entities required for a smart campaign. 
  
 sendMutateRequest 
 ( 
 googleAdsClient 
 , 
  
 customerId 
 , 
  
 operations 
 ); 
  
 } 
  
 /** 
 * Retrieves KeywordThemes using the given suggestion info. 
 * 
 * <p>Here we use the SuggestKeywordThemes method, which uses all of the business details included 
 * in the given SmartCampaignSuggestionInfo instance to generate keyword theme suggestions. This 
 * is the recommended way to generate keyword themes because it uses detailed information about 
 * your business, its location, and website content to generate keyword themes. 
 */ 
  
 private 
  
 List<KeywordTheme> 
  
 getKeywordThemeSuggestions 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long 
  
 customerId 
 , 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
 ) 
  
 { 
  
 // Creates the service client. 
  
 try 
  
 ( 
 SmartCampaignSuggestServiceClient 
  
 client 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createSmartCampaignSuggestServiceClient 
 ()) 
  
 { 
  
 // Sends the request. 
  
 SuggestKeywordThemesResponse 
  
 response 
  
 = 
  
 client 
 . 
 suggestKeywordThemes 
 ( 
  
 SuggestKeywordThemesRequest 
 . 
 newBuilder 
 () 
  
 . 
 setSuggestionInfo 
 ( 
 suggestionInfo 
 ) 
  
 . 
 setCustomerId 
 ( 
 String 
 . 
 valueOf 
 ( 
 customerId 
 )) 
  
 . 
 build 
 ()); 
  
 // Prints some information about the result. 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "Retrieved %d keyword theme suggestions from the SuggestKeywordThemes method.%n" 
 , 
  
 response 
 . 
 getKeywordThemesCount 
 ()); 
  
 return 
  
 new 
  
 ArrayList 
 ( 
 response 
 . 
 getKeywordThemesList 
 ()); 
  
 } 
  
 } 
  
 /** 
 * Retrieves KeywordThemeConstants that are derived from autocomplete data for the given keyword 
 * text, which are converted to a list of KeywordTheme objects before being returned. 
 */ 
  
 private 
  
 List<KeywordTheme> 
  
 getKeywordTextAutoCompletions 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 String 
  
 keywordText 
 ) 
  
 { 
  
 try 
  
 ( 
 KeywordThemeConstantServiceClient 
  
 client 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createKeywordThemeConstantServiceClient 
 ()) 
  
 { 
  
 SuggestKeywordThemeConstantsRequest 
  
 request 
  
 = 
  
 SuggestKeywordThemeConstantsRequest 
 . 
 newBuilder 
 () 
  
 . 
 setQueryText 
 ( 
 keywordText 
 ) 
  
 . 
 setCountryCode 
 ( 
 COUNTRY_CODE 
 ) 
  
 . 
 setLanguageCode 
 ( 
 LANGUAGE_CODE 
 ) 
  
 . 
 build 
 (); 
  
 SuggestKeywordThemeConstantsResponse 
  
 response 
  
 = 
  
 client 
 . 
 suggestKeywordThemeConstants 
 ( 
 request 
 ); 
  
 // Converts the keyword theme constants to KeywordTheme instances for consistency with the 
  
 // response from SmartCampaignSuggestService.SuggestKeywordThemes. 
  
 return 
  
 response 
 . 
 getKeywordThemeConstantsList 
 (). 
 stream 
 () 
  
 . 
 map 
 ( 
  
 keywordThemeConstant 
  
 - 
>  
 KeywordTheme 
 . 
 newBuilder 
 (). 
 setKeywordThemeConstant 
 ( 
 keywordThemeConstant 
 ). 
 build 
 ()) 
  
 . 
 collect 
 ( 
 Collectors 
 . 
 toList 
 ()); 
  
 } 
  
 } 
  
 /** 
 * Builds a SmartCampaignSuggestionInfo object with business details. 
 * 
 * <p>The details are used by the SmartCampaignSuggestService to suggest a budget amount as well 
 * as creatives for the ad. 
 * 
 * <p>Note that when retrieving ad creative suggestions it's required that the "final_url", 
 * "language_code" and "keyword_themes" fields are set on the SmartCampaignSuggestionInfo 
 * instance. 
 * 
 * @return SmartCampaignSuggestionInfo a SmartCampaignSuggestionInfo instance. 
 */ 
  
 private 
  
 SmartCampaignSuggestionInfo 
  
 getSmartCampaignSuggestionInfo 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 String 
  
 businessProfileLocation 
 , 
  
 String 
  
 businessName 
 ) 
  
 { 
  
 SmartCampaignSuggestionInfo 
 . 
 Builder 
  
 suggestionInfoBuilder 
  
 = 
  
 SmartCampaignSuggestionInfo 
 . 
 newBuilder 
 () 
  
 // Adds the URL of the campaign's landing page. 
  
 . 
 setFinalUrl 
 ( 
 LANDING_PAGE_URL 
 ) 
  
 // Adds the language code for the campaign. 
  
 . 
 setLanguageCode 
 ( 
 LANGUAGE_CODE 
 ) 
  
 // Constructs location information using the given geo target constant. It's also 
  
 // possible to provide a geographic proximity using the "proximity" field, 
  
 // for example: 
  
 // .setProximity( 
  
 //     ProximityInfo.newBuilder() 
  
 //         .setAddress( 
  
 //             AddressInfo.newBuilder() 
  
 //                 .setPostalCode(INSERT_POSTAL_CODE) 
  
 //                 .setProvinceCode(INSERT_PROVINCE_CODE) 
  
 //                 .setCountryCode(INSERT_COUNTRY_CODE) 
  
 //                 .setProvinceName(INSERT_PROVINCE_NAME) 
  
 //                 .setStreetAddress(INSERT_STREET_ADDRESS) 
  
 //                 .setStreetAddress2(INSERT_STREET_ADDRESS_2) 
  
 //                 .setCityName(INSERT_CITY_NAME) 
  
 //                 .build()) 
  
 //         .setRadius(INSERT_RADIUS) 
  
 //         .setRadiusUnits(INSERT_RADIUS_UNITS) 
  
 //         .build()) 
  
 // For more information on proximities see: 
  
 // https://developers.google.com/google-ads/api/reference/rpc/latest/ProximityInfo 
  
 // 
  
 // Adds LocationInfo objects to the list of locations. You have the option of 
  
 // providing multiple locations when using location-based suggestions. 
  
 . 
 setLocationList 
 ( 
  
 LocationList 
 . 
 newBuilder 
 () 
  
 // Sets one location to the resource name of the given geo target constant. 
  
 . 
 addLocations 
 ( 
  
 LocationInfo 
 . 
 newBuilder 
 () 
  
 . 
 setGeoTargetConstant 
 ( 
  
 ResourceNames 
 . 
 geoTargetConstant 
 ( 
 GEO_TARGET_CONSTANT 
 )) 
  
 . 
 build 
 ()) 
  
 . 
 build 
 ()) 
  
 // Adds a schedule detailing which days of the week the business is open. 
  
 // This schedule describes a schedule in which the business is open on 
  
 // Mondays from 9am to 5pm. 
  
 . 
 addAdSchedules 
 ( 
  
 AdScheduleInfo 
 . 
 newBuilder 
 () 
  
 // Sets the day of this schedule as Monday. 
  
 . 
 setDayOfWeek 
 ( 
 DayOfWeek 
 . 
 MONDAY 
 ) 
  
 // Sets the start hour to 9am. 
  
 . 
 setStartHour 
 ( 
 9 
 ) 
  
 // Sets the end hour to 5pm. 
  
 . 
 setEndHour 
 ( 
 17 
 ) 
  
 // Sets the start and end minute of zero, for example: 9:00 and 5:00. 
  
 . 
 setStartMinute 
 ( 
 MinuteOfHour 
 . 
 ZERO 
 ) 
  
 . 
 setEndMinute 
 ( 
 MinuteOfHour 
 . 
 ZERO 
 ) 
  
 . 
 build 
 ()); 
  
 // Sets either of the business_profile_location or business_name, depending on whichever is 
  
 // provided. 
  
 if 
  
 ( 
 businessProfileLocation 
  
 != 
  
 null 
 ) 
  
 { 
  
 suggestionInfoBuilder 
 . 
 setBusinessProfileLocation 
 ( 
 businessProfileLocation 
 ); 
  
 } 
  
 else 
  
 { 
  
 suggestionInfoBuilder 
 . 
 setBusinessContext 
 ( 
  
 BusinessContext 
 . 
 newBuilder 
 (). 
 setBusinessName 
 ( 
 businessName 
 ). 
 build 
 ()); 
  
 } 
  
 return 
  
 suggestionInfoBuilder 
 . 
 build 
 (); 
  
 } 
  
 /** 
 * Retrieves a suggested budget amount for a new budget. 
 * 
 * <p>Using the SmartCampaignSuggestService to determine a daily budget for new and existing Smart 
 * campaigns is highly recommended because it helps the campaigns achieve optimal performance. 
 * 
 * @return the recommended budget amount in micros ($1 = 1_000_000 micros). 
 */ 
  
 private 
  
 long 
  
 getBudgetSuggestions 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long 
  
 customerId 
 , 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
 ) 
  
 { 
  
 SuggestSmartCampaignBudgetOptionsRequest 
 . 
 Builder 
  
 request 
  
 = 
  
 SuggestSmartCampaignBudgetOptionsRequest 
 . 
 newBuilder 
 () 
  
 . 
 setCustomerId 
 ( 
 String 
 . 
 valueOf 
 ( 
 customerId 
 )); 
  
 // You can retrieve suggestions for an existing campaign by setting the 
  
 // "campaign" field of the request equal to the resource name of a campaign 
  
 // and leaving the rest of the request fields below unset: 
  
 // request.setCampaign("INSERT_CAMPAIGN_RESOURCE_NAME_HERE"); 
  
 // Uses the suggestion_info field instead, since these suggestions are for a new campaign. 
  
 request 
 . 
 setSuggestionInfo 
 ( 
 suggestionInfo 
 ); 
  
 // Issues a request to retrieve a budget suggestion. 
  
 try 
  
 ( 
 SmartCampaignSuggestServiceClient 
  
 client 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createSmartCampaignSuggestServiceClient 
 ()) 
  
 { 
  
 SuggestSmartCampaignBudgetOptionsResponse 
  
 response 
  
 = 
  
 client 
 . 
 suggestSmartCampaignBudgetOptions 
 ( 
 request 
 . 
 build 
 ()); 
  
 BudgetOption 
  
 recommendation 
  
 = 
  
 response 
 . 
 getRecommended 
 (); 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "A daily budget amount of %d micros was suggested, garnering an estimated minimum of %d" 
  
 + 
  
 " clicks and an estimated maximum of %d per day.%n" 
 , 
  
 recommendation 
 . 
 getDailyAmountMicros 
 (), 
  
 recommendation 
 . 
 getMetrics 
 (). 
 getMinDailyClicks 
 (), 
  
 recommendation 
 . 
 getMetrics 
 (). 
 getMaxDailyClicks 
 ()); 
  
 return 
  
 recommendation 
 . 
 getDailyAmountMicros 
 (); 
  
 } 
  
 } 
  
 /** 
 * Retrieves creative suggestions for a Smart campaign ad. 
 * 
 * <p>Using the SmartCampaignSuggestService to suggest creatives for new and existing Smart 
 * campaigns is highly recommended because it helps the campaigns achieve optimal performance. 
 * 
 * @return SmartCampaignAdInfo a SmartCampaignAdInfo instance with suggested headlines and 
 *     descriptions. 
 */ 
  
 private 
  
 SmartCampaignAdInfo 
  
 getAdSuggestions 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long 
  
 customerId 
 , 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
 ) 
  
 { 
  
 // Unlike the SuggestSmartCampaignBudgetOptions method, it's only possible to use 
  
 // suggestion_info to retrieve ad creative suggestions. 
  
 // Issues a request to retrieve ad creative suggestions. 
  
 try 
  
 ( 
 SmartCampaignSuggestServiceClient 
  
 smartCampaignSuggestService 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createSmartCampaignSuggestServiceClient 
 ()) 
  
 { 
  
 SuggestSmartCampaignAdResponse 
  
 response 
  
 = 
  
 smartCampaignSuggestService 
 . 
 suggestSmartCampaignAd 
 ( 
  
 SuggestSmartCampaignAdRequest 
 . 
 newBuilder 
 () 
  
 . 
 setCustomerId 
 ( 
 Long 
 . 
 toString 
 ( 
 customerId 
 )) 
  
 . 
 setSuggestionInfo 
 ( 
 suggestionInfo 
 ) 
  
 . 
 build 
 ()); 
  
 // The SmartCampaignAdInfo object in the response contains a list of up to three headlines 
  
 // and two descriptions. Note that some of the suggestions may have empty strings as text. 
  
 // Before setting these on the ad you should review them and filter out any empty values. 
  
 SmartCampaignAdInfo 
  
 adSuggestions 
  
 = 
  
 response 
 . 
 getAdInfo 
 (); 
  
 for 
  
 ( 
 AdTextAsset 
  
 headline 
  
 : 
  
 adSuggestions 
 . 
 getHeadlinesList 
 ()) 
  
 { 
  
 System 
 . 
 out 
 . 
 println 
 ( 
 ! 
 headline 
 . 
 getText 
 (). 
 isEmpty 
 () 
  
 ? 
  
 headline 
 . 
 getText 
 () 
  
 : 
  
 "None" 
 ); 
  
 } 
  
 for 
  
 ( 
 AdTextAsset 
  
 description 
  
 : 
  
 adSuggestions 
 . 
 getDescriptionsList 
 ()) 
  
 { 
  
 System 
 . 
 out 
 . 
 println 
 ( 
 ! 
 description 
 . 
 getText 
 (). 
 isEmpty 
 () 
  
 ? 
  
 description 
 . 
 getText 
 () 
  
 : 
  
 "None" 
 ); 
  
 } 
  
 return 
  
 adSuggestions 
 ; 
  
 } 
  
 } 
  
 /** 
 * Creates a MutateOperation that creates a new CampaignBudget. 
 * 
 * <p>A temporary ID will be assigned to this campaign budget so that it can be referenced by 
 * other objects being created in the same Mutate request. 
 */ 
  
 private 
  
 MutateOperation 
  
 createCampaignBudgetOperation 
 ( 
 long 
  
 customerId 
 , 
  
 long 
  
 dailyBudgetMicros 
 ) 
  
 { 
  
 MutateOperation 
 . 
 Builder 
  
 builder 
  
 = 
  
 MutateOperation 
 . 
 newBuilder 
 (); 
  
 builder 
  
 . 
 getCampaignBudgetOperationBuilder 
 () 
  
 . 
 getCreateBuilder 
 () 
  
 . 
 setName 
 ( 
 "Smart campaign budget " 
  
 + 
  
 CodeSampleHelper 
 . 
 getShortPrintableDateTime 
 ()) 
  
 . 
 setDeliveryMethod 
 ( 
 BudgetDeliveryMethod 
 . 
 STANDARD 
 ) 
  
 // A budget used for Smart campaigns must have the type SMART_CAMPAIGN. 
  
 . 
 setType 
 ( 
 BudgetType 
 . 
 SMART_CAMPAIGN 
 ) 
  
 // The suggested budget amount from the SmartCampaignSuggestService is for a _daily_ budget. 
  
 // We don't need to specify that here, because the budget period already defaults to DAILY. 
  
 . 
 setAmountMicros 
 ( 
 dailyBudgetMicros 
 ) 
  
 // Sets a temporary ID in the budget's resource name so it can be referenced by the campaign 
  
 // in later steps. 
  
 . 
 setResourceName 
 ( 
 ResourceNames 
 . 
 campaignBudget 
 ( 
 customerId 
 , 
  
 BUDGET_TEMPORARY_ID 
 )); 
  
 return 
  
 builder 
 . 
 build 
 (); 
  
 } 
  
 /** 
 * Creates a MutateOperation that creates a new Smart campaign. 
 * 
 * <p>A temporary ID will be assigned to this campaign so that it can be referenced by other 
 * objects being created in the same Mutate request. 
 */ 
  
 private 
  
 MutateOperation 
  
 createSmartCampaignOperation 
 ( 
 long 
  
 customerId 
 ) 
  
 { 
  
 MutateOperation 
 . 
 Builder 
  
 builder 
  
 = 
  
 MutateOperation 
 . 
 newBuilder 
 (); 
  
 builder 
  
 . 
 getCampaignOperationBuilder 
 () 
  
 . 
 getCreateBuilder 
 () 
  
 . 
 setName 
 ( 
 "Smart campaign " 
  
 + 
  
 CodeSampleHelper 
 . 
 getShortPrintableDateTime 
 ()) 
  
 . 
 setStatus 
 ( 
 CampaignStatus 
 . 
 PAUSED 
 ) 
  
 . 
 setAdvertisingChannelType 
 ( 
 AdvertisingChannelType 
 . 
 SMART 
 ) 
  
 . 
 setAdvertisingChannelSubType 
 ( 
 AdvertisingChannelSubType 
 . 
 SMART_CAMPAIGN 
 ) 
  
 // Assigns the resource name with a temporary ID. 
  
 . 
 setResourceName 
 ( 
 ResourceNames 
 . 
 campaign 
 ( 
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 )) 
  
 . 
 setCampaignBudget 
 ( 
 ResourceNames 
 . 
 campaignBudget 
 ( 
 customerId 
 , 
  
 BUDGET_TEMPORARY_ID 
 )) 
  
 // Declares whether this campaign serves political ads targeting the EU. 
  
 . 
 setContainsEuPoliticalAdvertising 
 ( 
 DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING 
 ); 
  
 return 
  
 builder 
 . 
 build 
 (); 
  
 } 
  
 /** 
 * Creates a MutateOperation to create a new SmartCampaignSetting. 
 * 
 * <p>SmartCampaignSettings are unique in that they only support UPDATE operations, which are used 
 * to update and create them. Below we will use a temporary ID in the resource name to associate 
 * it with the campaign created in the previous step. 
 */ 
  
 private 
  
 MutateOperation 
  
 createSmartCampaignSettingOperation 
 ( 
  
 long 
  
 customerId 
 , 
  
 String 
  
 businessProfileLocation 
 , 
  
 String 
  
 businessName 
 ) 
  
 { 
  
 MutateOperation 
 . 
 Builder 
  
 builder 
  
 = 
  
 MutateOperation 
 . 
 newBuilder 
 (); 
  
 SmartCampaignSetting 
 . 
 Builder 
  
 settingBuilder 
  
 = 
  
 builder 
  
 . 
 getSmartCampaignSettingOperationBuilder 
 () 
  
 . 
 getUpdateBuilder 
 () 
  
 // Sets a temporary ID in the campaign setting's resource name to associate it with 
  
 // the campaign created in the previous step. 
  
 . 
 setResourceName 
 ( 
  
 ResourceNames 
 . 
 smartCampaignSetting 
 ( 
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 )); 
  
 // Configures the SmartCampaignSetting using many of the same details used to 
  
 // generate a budget suggestion. 
  
 settingBuilder 
  
 . 
 setFinalUrl 
 ( 
 LANDING_PAGE_URL 
 ) 
  
 . 
 setAdvertisingLanguageCode 
 ( 
 LANGUAGE_CODE 
 ) 
  
 . 
 getPhoneNumberBuilder 
 () 
  
 . 
 setCountryCode 
 ( 
 COUNTRY_CODE 
 ) 
  
 . 
 setPhoneNumber 
 ( 
 PHONE_NUMBER 
 ); 
  
 // It's required that either a business profile location resource name or a business name is 
  
 // added to the SmartCampaignSetting. 
  
 if 
  
 ( 
 businessProfileLocation 
  
 != 
  
 null 
 ) 
  
 { 
  
 settingBuilder 
 . 
 setBusinessProfileLocation 
 ( 
 businessProfileLocation 
 ); 
  
 } 
  
 else 
  
 { 
  
 settingBuilder 
 . 
 setBusinessName 
 ( 
 businessName 
 ); 
  
 } 
  
 builder 
  
 . 
 getSmartCampaignSettingOperationBuilder 
 () 
  
 . 
 setUpdateMask 
 ( 
 FieldMasks 
 . 
 allSetFieldsOf 
 ( 
 settingBuilder 
 . 
 build 
 ())); 
  
 return 
  
 builder 
 . 
 build 
 (); 
  
 } 
  
 /** 
 * Creates a MutateOperation that creates a new ad group. 
 * 
 * <p>A temporary ID will be used in the campaign resource name for this ad group to associate it 
 * with the Smart campaign created in earlier steps. A temporary ID will also be used for its own 
 * resource name so that we can associate an ad group ad with it later in the process. 
 * 
 * <p>Only one ad group can be created for a given Smart campaign. 
 */ 
  
 private 
  
 MutateOperation 
  
 createAdGroupOperation 
 ( 
 long 
  
 customerId 
 ) 
  
 { 
  
 MutateOperation 
 . 
 Builder 
  
 builder 
  
 = 
  
 MutateOperation 
 . 
 newBuilder 
 (); 
  
 builder 
  
 . 
 getAdGroupOperationBuilder 
 () 
  
 . 
 getCreateBuilder 
 () 
  
 . 
 setResourceName 
 ( 
 ResourceNames 
 . 
 adGroup 
 ( 
 customerId 
 , 
  
 AD_GROUP_TEMPORARY_ID 
 )) 
  
 . 
 setName 
 ( 
 "Smart campaign ad group " 
  
 + 
  
 CodeSampleHelper 
 . 
 getShortPrintableDateTime 
 ()) 
  
 . 
 setCampaign 
 ( 
 ResourceNames 
 . 
 campaign 
 ( 
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 )) 
  
 . 
 setType 
 ( 
 AdGroupType 
 . 
 SMART_CAMPAIGN_ADS 
 ); 
  
 return 
  
 builder 
 . 
 build 
 (); 
  
 } 
  
 /** 
 * Creates a MutateOperation that creates a new ad group ad. 
 * 
 * <p>A temporary ID will be used in the ad group resource name for this ad group ad to associate 
 * it with the ad group created in earlier steps. 
 */ 
  
 private 
  
 MutateOperation 
  
 createAdGroupAdOperation 
 ( 
  
 long 
  
 customerId 
 , 
  
 SmartCampaignAdInfo 
  
 adSuggestions 
 ) 
  
 { 
  
 MutateOperation 
 . 
 Builder 
  
 opBuilder 
  
 = 
  
 MutateOperation 
 . 
 newBuilder 
 (); 
  
 // Constructs an Ad instance containing a SmartCampaignAd. 
  
 Ad 
 . 
 Builder 
  
 adBuilder 
  
 = 
  
 Ad 
 . 
 newBuilder 
 (); 
  
 adBuilder 
  
 . 
 setType 
 ( 
 AdType 
 . 
 SMART_CAMPAIGN_AD 
 ) 
  
 // The SmartCampaignAdInfo object includes headlines and descriptions retrieved 
  
 // from the suggestSmartCampaignAd method. It's recommended that users review and approve or 
  
 // update these creatives before they're set on the ad. It's possible that some or all of 
  
 // these assets may contain empty texts, which should not be set on the ad and instead 
  
 // should be replaced with meaningful texts from the user. Below we just accept the 
  
 // creatives that were suggested while filtering out empty assets, but individual workflows 
  
 // will vary here. 
  
 . 
 getSmartCampaignAdBuilder 
 () 
  
 . 
 addAllHeadlines 
 ( 
  
 adSuggestions 
 . 
 getHeadlinesList 
 (). 
 stream 
 () 
  
 . 
 filter 
 ( 
 h 
  
 - 
>  
 h 
 . 
 hasText 
 ()) 
  
 . 
 collect 
 ( 
 Collectors 
 . 
 toList 
 ())) 
  
 . 
 addAllDescriptions 
 ( 
  
 adSuggestions 
 . 
 getDescriptionsList 
 (). 
 stream 
 () 
  
 . 
 filter 
 ( 
 d 
  
 - 
>  
 d 
 . 
 hasText 
 ()) 
  
 . 
 collect 
 ( 
 Collectors 
 . 
 toList 
 ())); 
  
 // Adds additional headlines + descriptions if we didn't get enough back from the suggestion 
  
 // service. 
  
 int 
  
 numHeadlines 
  
 = 
  
 adBuilder 
 . 
 getSmartCampaignAdBuilder 
 (). 
 getHeadlinesCount 
 (); 
  
 if 
  
 ( 
 numHeadlines 
 < 
 NUM_REQUIRED_HEADLINES 
 ) 
  
 { 
  
 for 
  
 ( 
 int 
  
 i 
  
 = 
  
 0 
 ; 
  
 i 
 < 
 NUM_REQUIRED_HEADLINES 
  
 - 
  
 numHeadlines 
 ; 
  
 ++ 
 i 
 ) 
  
 { 
  
 adBuilder 
  
 . 
 getSmartCampaignAdBuilder 
 () 
  
 . 
 addHeadlines 
 ( 
 AdTextAsset 
 . 
 newBuilder 
 (). 
 setText 
 ( 
 "Placeholder headline " 
  
 + 
  
 i 
 ). 
 build 
 ()); 
  
 } 
  
 } 
  
 if 
  
 ( 
 adSuggestions 
 . 
 getDescriptionsCount 
 () 
 < 
 NUM_REQUIRED_DESCRIPTIONS 
 ) 
  
 { 
  
 int 
  
 numDescriptions 
  
 = 
  
 adBuilder 
 . 
 getSmartCampaignAdBuilder 
 (). 
 getDescriptionsCount 
 (); 
  
 for 
  
 ( 
 int 
  
 i 
  
 = 
  
 0 
 ; 
  
 i 
 < 
 NUM_REQUIRED_DESCRIPTIONS 
  
 - 
  
 numDescriptions 
 ; 
  
 ++ 
 i 
 ) 
  
 { 
  
 adBuilder 
  
 . 
 getSmartCampaignAdBuilder 
 () 
  
 . 
 addDescriptions 
 ( 
  
 AdTextAsset 
 . 
 newBuilder 
 (). 
 setText 
 ( 
 "Placeholder description " 
  
 + 
  
 i 
 ). 
 build 
 ()); 
  
 } 
  
 } 
  
 opBuilder 
  
 . 
 getAdGroupAdOperationBuilder 
 () 
  
 . 
 getCreateBuilder 
 () 
  
 . 
 setAdGroup 
 ( 
 ResourceNames 
 . 
 adGroup 
 ( 
 customerId 
 , 
  
 AD_GROUP_TEMPORARY_ID 
 )) 
  
 . 
 setAd 
 ( 
 adBuilder 
 ); 
  
 return 
  
 opBuilder 
 . 
 build 
 (); 
  
 } 
  
 /** 
 * Creates {@link com.google.ads.googleads.v21.resources.CampaignCriterion} operations for add 
 * each {@link KeywordThemeInfo}. 
 */ 
  
 private 
  
 Collection 
< ? 
  
 extends 
  
 MutateOperation 
>  
 createCampaignCriterionOperations 
 ( 
  
 long 
  
 customerId 
 , 
  
 List<KeywordThemeInfo> 
  
 keywordThemeInfos 
 , 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 keywordThemeOperations 
  
 = 
  
 keywordThemeInfos 
 . 
 stream 
 () 
  
 . 
 map 
 ( 
  
 keywordTheme 
  
 - 
>  
 { 
  
 MutateOperation 
 . 
 Builder 
  
 builder 
  
 = 
  
 MutateOperation 
 . 
 newBuilder 
 (); 
  
 builder 
  
 . 
 getCampaignCriterionOperationBuilder 
 () 
  
 . 
 getCreateBuilder 
 () 
  
 . 
 setCampaign 
 ( 
 ResourceNames 
 . 
 campaign 
 ( 
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 )) 
  
 . 
 setKeywordTheme 
 ( 
 keywordTheme 
 ); 
  
 return 
  
 builder 
 . 
 build 
 (); 
  
 }) 
  
 . 
 collect 
 ( 
 Collectors 
 . 
 toList 
 ()); 
  
 List<MutateOperation> 
  
 locationOperations 
  
 = 
  
 suggestionInfo 
 . 
 getLocationList 
 (). 
 getLocationsList 
 (). 
 stream 
 () 
  
 . 
 map 
 ( 
  
 location 
  
 - 
>  
 { 
  
 MutateOperation 
 . 
 Builder 
  
 builder 
  
 = 
  
 MutateOperation 
 . 
 newBuilder 
 (); 
  
 builder 
  
 . 
 getCampaignCriterionOperationBuilder 
 () 
  
 . 
 getCreateBuilder 
 () 
  
 . 
 setCampaign 
 ( 
 ResourceNames 
 . 
 campaign 
 ( 
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 )) 
  
 . 
 setLocation 
 ( 
 location 
 ); 
  
 return 
  
 builder 
 . 
 build 
 (); 
  
 }) 
  
 . 
 collect 
 ( 
 Collectors 
 . 
 toList 
 ()); 
  
 return 
  
 Stream 
 . 
 concat 
 ( 
 keywordThemeOperations 
 . 
 stream 
 (), 
  
 locationOperations 
 . 
 stream 
 ()) 
  
 . 
 collect 
 ( 
 Collectors 
 . 
 toList 
 ()); 
  
 } 
  
 /** 
 * Sends a mutate request with a group of mutate operations. 
 * 
 * <p>The {@link GoogleAdsServiceClient} allows batching together a list of operations. These are 
 * executed sequentially, and later operations my refer to previous operations via temporary IDs. 
 * For more detail on this, please refer to 
 * https://developers.google.com/google-ads/api/docs/batch-processing/temporary-ids. 
 */ 
  
 private 
  
 void 
  
 sendMutateRequest 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long 
  
 customerId 
 , 
  
 List<MutateOperation> 
  
 operations 
 ) 
  
 { 
  
 try 
  
 ( 
 GoogleAdsServiceClient 
  
 client 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createGoogleAdsServiceClient 
 ()) 
  
 { 
  
 MutateGoogleAdsResponse 
  
 outerResponse 
  
 = 
  
 client 
 . 
 mutate 
 ( 
 String 
 . 
 valueOf 
 ( 
 customerId 
 ), 
  
 operations 
 ); 
  
 for 
  
 ( 
 MutateOperationResponse 
  
 innerResponse 
  
 : 
  
 outerResponse 
 . 
 getMutateOperationResponsesList 
 ()) 
  
 { 
  
 OneofDescriptor 
  
 oneofDescriptor 
  
 = 
  
 innerResponse 
 . 
 getDescriptorForType 
 (). 
 getOneofs 
 (). 
 stream 
 () 
  
 . 
 filter 
 ( 
 o 
  
 - 
>  
 o 
 . 
 getName 
 (). 
 equals 
 ( 
 "response" 
 )) 
  
 . 
 findFirst 
 () 
  
 . 
 get 
 (); 
  
 Message 
  
 createdEntity 
  
 = 
  
 ( 
 Message 
 ) 
  
 innerResponse 
 . 
 getField 
 ( 
 innerResponse 
 . 
 getOneofFieldDescriptor 
 ( 
 oneofDescriptor 
 )); 
  
 String 
  
 resourceName 
  
 = 
  
 ( 
 String 
 ) 
  
 createdEntity 
 . 
 getField 
 ( 
  
 createdEntity 
 . 
 getDescriptorForType 
 (). 
 findFieldByName 
 ( 
 "resource_name" 
 )); 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "Created a(n) %s with resource name: '%s'.%n" 
 , 
  
 createdEntity 
 . 
 getClass 
 (). 
 getSimpleName 
 (), 
  
 resourceName 
 ); 
  
 } 
  
 } 
  
 } 
  
 /** 
 * Provides a helper method to convert a list of {@link KeywordTheme} objects to a list of {@link 
 * KeywordThemeInfo} objects. 
 */ 
  
 private 
  
 List<KeywordThemeInfo> 
  
 getKeywordThemeInfos 
 ( 
 List<KeywordTheme> 
  
 keywordThemes 
 ) 
  
 { 
  
 return 
  
 keywordThemes 
 . 
 stream 
 () 
  
 . 
 map 
 ( 
  
 keywordTheme 
  
 - 
>  
 { 
  
 KeywordThemeInfo 
 . 
 Builder 
  
 keywordThemeInfoBuilder 
  
 = 
  
 KeywordThemeInfo 
 . 
 newBuilder 
 (); 
  
 // Checks if the keyword_theme_constant field is set. 
  
 if 
  
 ( 
 keywordTheme 
 . 
 hasKeywordThemeConstant 
 ()) 
  
 { 
  
 return 
  
 keywordThemeInfoBuilder 
  
 . 
 setKeywordThemeConstant 
 ( 
  
 keywordTheme 
 . 
 getKeywordThemeConstant 
 (). 
 getResourceName 
 ()) 
  
 . 
 build 
 (); 
  
 } 
  
 else 
  
 if 
  
 ( 
 keywordTheme 
 . 
 hasFreeFormKeywordTheme 
 ()) 
  
 { 
  
 return 
  
 keywordThemeInfoBuilder 
  
 . 
 setFreeFormKeywordTheme 
 ( 
 keywordTheme 
 . 
 getFreeFormKeywordTheme 
 ()) 
  
 . 
 build 
 (); 
  
 } 
  
 else 
  
 { 
  
 throw 
  
 new 
  
 IllegalArgumentException 
 ( 
  
 String 
 . 
 format 
 ( 
 "A malformed KeywordTheme was encountered: %s" 
 , 
  
 keywordTheme 
 )); 
  
 } 
  
 }) 
  
 . 
 collect 
 ( 
 Collectors 
 . 
 toCollection 
 ( 
 ArrayList 
 :: 
 new 
 )); 
  
 } 
 } 
  
  

C#

 // Copyright 2021 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. 
 using 
  
 System 
 ; 
 using 
  
 System.Collections.Generic 
 ; 
 using 
  
 System.Linq 
 ; 
 using 
  
 CommandLine 
 ; 
 using 
  
 Google.Ads.Gax.Examples 
 ; 
 using 
  
 Google.Ads.Gax.Util 
 ; 
 using 
  
 Google.Ads.GoogleAds.Lib 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Common 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Enums 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Errors 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Resources 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Services 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 AdGroupTypeEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 AdvertisingChannelTypeEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 AdvertisingChannelSubTypeEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 BudgetTypeEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 CampaignStatusEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 EuPoliticalAdvertisingStatusEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Services 
 . 
 SmartCampaignSuggestionInfo 
 . 
 Types 
 ; 
 namespace 
  
 Google.Ads.GoogleAds.Examples.V21 
 { 
  
 /// <summary> 
  
 /// This example shows how to create a Smart Campaign. 
  
 /// 
  
 /// More details on Smart Campaigns can be found here: 
  
 /// https://support.google.com/google-ads/answer/7652860 
  
 /// </summary> 
  
 public 
  
 class 
  
 AddSmartCampaign 
  
 : 
  
 ExampleBase 
  
 { 
  
 /// <summary> 
  
 /// Command line options for running the <see cref="AddSmartCampaign"/> example. 
  
 /// </summary> 
  
 public 
  
 class 
  
 Options 
  
 : 
  
 OptionsBase 
  
 { 
  
 /// <summary> 
  
 /// The Google Ads customer ID. 
  
 /// </summary> 
  
 [Option("customerId", Required = true, HelpText = 
 "The Google Ads customer ID.")] 
  
 public 
  
 long 
  
 CustomerId 
  
 { 
  
 get 
 ; 
  
 set 
 ; 
  
 } 
  
 /// <summary> 
  
 /// A keyword text used to retrieve keyword theme constant suggestions from the 
  
 /// KeywordThemeConstantService. These keyword theme suggestions are generated 
  
 /// using auto-completion data for the given text and may help improve the 
  
 /// performance of the Smart campaign. 
  
 /// </summary> 
  
 [Option("keywordText", Required = false, HelpText = 
 "A keyword text used to retrieve keyword theme constant suggestions from the " + 
 "KeywordThemeConstantService. These keyword theme suggestions are generated " + 
 "using auto-completion data for the given text and may help improve the " + 
 "performance of the Smart campaign.", 
 Default = DEFAULT_KEYWORD_TEXT)] 
  
 public 
  
 string 
  
 Keyword 
  
 { 
  
 get 
 ; 
  
 set 
 ; 
  
 } 
  
 /// <summary> 
  
 /// A keyword text used to create a freeform keyword theme, which is entirely 
  
 /// user-specified and not derived from any suggestion service. Using free-form 
  
 /// keyword themes is typically not recommended because they are less effective 
  
 /// than suggested keyword themes, however they are useful in situations where a 
  
 /// very specific term needs to be targeted. 
  
 /// </summary> 
  
 [Option("freeformKeywordText", Required = false, HelpText = 
 "A keyword text used to create a freeform keyword theme, which is entirely " + 
 "user-specified and not derived from any suggestion service. Using free-form " + 
 "keyword themes is typically not recommended because they are less effective " + 
 "than suggested keyword themes, however they are useful in situations where a " + 
 "very specific term needs to be targeted.", 
 Default = DEFAULT_KEYWORD_TEXT)] 
  
 public 
  
 string 
  
 FreeformKeywordText 
  
 { 
  
 get 
 ; 
  
 set 
 ; 
  
 } 
  
 /// <summary> 
  
 /// The identifier for a Business Profile location</summary> 
  
 [Option("BusinessProfileLocation", Required = false, HelpText = 
 "The identifier for a Business Profile location.")] 
  
 public 
  
 string 
  
 BusinessProfileLocation 
  
 { 
  
 get 
 ; 
  
 set 
 ; 
  
 } 
  
 /// <summary> 
  
 /// The name of a Business Profile business. This is required if a business 
  
 /// location ID is not provided. 
  
 /// </summary> 
  
 [Option("businessName", Required = false, HelpText = 
 "The name of a Business Profile business. This is required if a " + 
 "business location ID is not provided.")] 
  
 public 
  
 string 
  
 BusinessName 
  
 { 
  
 get 
 ; 
  
 set 
 ; 
  
 } 
  
 } 
  
 /// <summary> 
  
 /// Main method, to run this code example as a standalone application. 
  
 /// </summary> 
  
 /// <param name="args">The command line arguments.</param> 
  
 public 
  
 static 
  
 void 
  
 Main 
 ( 
 string 
 [] 
  
 args 
 ) 
  
 { 
  
 Options 
  
 options 
  
 = 
  
 ExampleUtilities 
 . 
 ParseCommandLine<Options> 
 ( 
 args 
 ); 
  
 AddSmartCampaign 
  
 codeExample 
  
 = 
  
 new 
  
 AddSmartCampaign 
 (); 
  
 Console 
 . 
 WriteLine 
 ( 
 codeExample 
 . 
 Description 
 ); 
  
 codeExample 
 . 
 Run 
 ( 
 new 
  
 GoogleAdsClient 
 (), 
  
 options 
 . 
 CustomerId 
 , 
  
 options 
 . 
 Keyword 
 , 
  
 options 
 . 
 FreeformKeywordText 
 , 
  
 options 
 . 
 BusinessProfileLocation 
 , 
  
 options 
 . 
 BusinessName 
 ); 
  
 } 
  
 private 
  
 const 
  
 string 
  
 DEFAULT_KEYWORD_TEXT 
  
 = 
  
 "travel" 
 ; 
  
 // Geo target constant for New York City. 
  
 private 
  
 const 
  
 long 
  
 GEO_TARGET_CONSTANT 
  
 = 
  
 1023191 
 ; 
  
 private 
  
 const 
  
 string 
  
 COUNTRY_CODE 
  
 = 
  
 "US" 
 ; 
  
 private 
  
 const 
  
 string 
  
 LANGUAGE_CODE 
  
 = 
  
 "en" 
 ; 
  
 private 
  
 const 
  
 string 
  
 LANDING_PAGE_URL 
  
 = 
  
 "http://www.example.com" 
 ; 
  
 private 
  
 const 
  
 string 
  
 PHONE_NUMBER 
  
 = 
  
 "800-555-0100" 
 ; 
  
 private 
  
 const 
  
 long 
  
 BUDGET_TEMPORARY_ID 
  
 = 
  
 - 
 1 
 ; 
  
 private 
  
 const 
  
 long 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
  
 = 
  
 - 
 2 
 ; 
  
 private 
  
 const 
  
 long 
  
 AD_GROUP_TEMPORARY_ID 
  
 = 
  
 - 
 3 
 ; 
  
 private 
  
 const 
  
 int 
  
 NUM_REQUIRED_HEADLINES 
  
 = 
  
 3 
 ; 
  
 private 
  
 const 
  
 int 
  
 NUM_REQUIRED_DESCRIPTIONS 
  
 = 
  
 2 
 ; 
  
 /// <summary> 
  
 /// Returns a description about the code example. 
  
 /// </summary> 
  
 public 
  
 override 
  
 string 
  
 Description 
  
 = 
>  
 "This example shows how to create a Smart Campaign.\nMore details on Smart " 
  
 + 
  
 "Campaigns can be found here: https: //support.google.com/google-ads/answer/7652860" 
 ; 
  
 /// <summary> 
  
 /// Runs the code example. 
  
 /// </summary> 
  
 /// <param name="client">The Google Ads client.</param> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <param name="keywordText">A keyword string used for generating keyword themes.</param> 
  
 /// <param name="freeFormKeywordText">A keyword used to create a free-form keyword theme. 
  
 /// </param> 
  
 /// <param name="businessProfileLocation">The identifier of a Business Profile location. 
  
 /// </param> 
  
 /// <param name="businessName">The name of a Business Profile business.</param> 
  
 public 
  
 void 
  
 Run 
 ( 
 GoogleAdsClient 
  
 client 
 , 
  
 long 
  
 customerId 
 , 
  
 string 
  
 keywordText 
 , 
  
 string 
  
 freeFormKeywordText 
 , 
  
 string 
  
 businessProfileLocation 
 , 
  
 string 
  
 businessName 
 ) 
  
 { 
  
 GoogleAdsServiceClient 
  
 googleAdsServiceClient 
  
 = 
  
 client 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 GoogleAdsService 
 ); 
  
 try 
  
 { 
  
 // Gets the SmartCampaignSuggestionInfo object which acts as the basis for many 
  
 // of the entities necessary to create a Smart campaign. It will be reused a number 
  
 // of times to retrieve suggestions for keyword themes, budget amount, ad 
  
 //creatives, and campaign criteria. 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
  
 = 
  
 GetSmartCampaignSuggestionInfo 
 ( 
 client 
 , 
  
 businessProfileLocation 
 , 
  
 businessName 
 ); 
  
 // Generates a list of keyword themes using the SuggestKeywordThemes method on the 
  
 // SmartCampaignSuggestService. It is strongly recommended that you use this 
  
 // strategy for generating keyword themes. 
  
 List<KeywordThemeConstant> 
  
 keywordThemeConstants 
  
 = 
  
 GetKeywordThemeSuggestions 
 ( 
 client 
 , 
  
 customerId 
 , 
  
 suggestionInfo 
 ); 
  
 // Optionally retrieves auto-complete suggestions for the given keyword text and 
  
 // adds them to the list of keyWordThemeConstants. 
  
 if 
  
 ( 
 keywordText 
  
 != 
  
 null 
 ) 
  
 { 
  
 keywordThemeConstants 
 . 
 AddRange 
 ( 
 GetKeywordTextAutoCompletions 
 ( 
  
 client 
 , 
  
 keywordText 
 )); 
  
 } 
  
 // Converts the KeywordThemeConstants to KeywordThemeInfos. 
  
 List<KeywordThemeInfo> 
  
 keywordThemeInfos 
  
 = 
  
 keywordThemeConstants 
 . 
 Select 
 ( 
  
 constant 
  
 = 
>  
 new 
  
 KeywordThemeInfo 
  
 { 
  
 KeywordThemeConstant 
  
 = 
  
 constant 
 . 
 ResourceName 
  
 }) 
  
 . 
 ToList 
 (); 
  
 // Optionally includes any freeform keywords verbatim. 
  
 if 
  
 ( 
 freeFormKeywordText 
  
 != 
  
 null 
 ) 
  
 { 
  
 keywordThemeInfos 
 . 
 Add 
 ( 
 new 
  
 KeywordThemeInfo 
 () 
  
 { 
  
 FreeFormKeywordTheme 
  
 = 
  
 freeFormKeywordText 
  
 }); 
  
 } 
  
 // Includes the keyword suggestions in the overall SuggestionInfo object. 
  
 suggestionInfo 
 . 
 KeywordThemes 
 . 
 Add 
 ( 
 keywordThemeInfos 
 ); 
  
 SmartCampaignAdInfo 
  
 adSuggestions 
  
 = 
  
 GetAdSuggestions 
 ( 
 client 
 , 
  
 customerId 
 , 
  
 suggestionInfo 
 ); 
  
 long 
  
 suggestedBudgetAmount 
  
 = 
  
 GetBudgetSuggestion 
 ( 
 client 
 , 
  
 customerId 
 , 
  
 suggestionInfo 
 ); 
  
 // The below methods create and return MutateOperations that we later provide to 
  
 // the GoogleAdsService.Mutate method in order to create the entities in a single 
  
 // request. Since the entities for a Smart campaign are closely tied to one-another 
  
 // it's considered a best practice to create them in a single Mutate request; the 
  
 // entities will either all complete successfully or fail entirely, leaving no 
  
 // orphaned entities. See: 
  
 // https://developers.google.com/google-ads/api/docs/mutating/overview 
  
 MutateOperation 
  
 campaignBudgetOperation 
  
 = 
  
 CreateCampaignBudgetOperation 
 ( 
 customerId 
 , 
  
 suggestedBudgetAmount 
 ); 
  
 MutateOperation 
  
 smartCampaignOperation 
  
 = 
  
 CreateSmartCampaignOperation 
 ( 
 customerId 
 ); 
  
 MutateOperation 
  
 smartCampaignSettingOperation 
  
 = 
  
 CreateSmartCampaignSettingOperation 
 ( 
 customerId 
 , 
  
 businessProfileLocation 
 , 
  
 businessName 
 ); 
  
 IEnumerable<MutateOperation> 
  
 campaignCriterionOperations 
  
 = 
  
 CreateCampaignCriterionOperations 
 ( 
 customerId 
 , 
  
 keywordThemeInfos 
 , 
  
 suggestionInfo 
 ); 
  
 MutateOperation 
  
 adGroupOperation 
  
 = 
  
 CreateAdGroupOperation 
 ( 
 customerId 
 ); 
  
 MutateOperation 
  
 adGroupAdOperation 
  
 = 
  
 CreateAdGroupAdOperation 
 ( 
 customerId 
 , 
  
 adSuggestions 
 ); 
  
 // Send the operations in a single mutate request. 
  
 MutateGoogleAdsRequest 
  
 mutateGoogleAdsRequest 
  
 = 
  
 new 
  
 MutateGoogleAdsRequest 
  
 { 
  
 CustomerId 
  
 = 
  
 customerId 
 . 
 ToString 
 () 
  
 }; 
  
 // It's important to create these entities in this order because they depend on 
  
 // each other, for example the SmartCampaignSetting and ad group depend on the 
  
 // campaign, and the ad group ad depends on the ad group. 
  
 mutateGoogleAdsRequest 
 . 
 MutateOperations 
 . 
 Add 
 ( 
 campaignBudgetOperation 
 ); 
  
 mutateGoogleAdsRequest 
 . 
 MutateOperations 
 . 
 Add 
 ( 
 smartCampaignOperation 
 ); 
  
 mutateGoogleAdsRequest 
 . 
 MutateOperations 
 . 
 Add 
 ( 
 smartCampaignSettingOperation 
 ); 
  
 mutateGoogleAdsRequest 
 . 
 MutateOperations 
 . 
 Add 
 ( 
 campaignCriterionOperations 
 ); 
  
 mutateGoogleAdsRequest 
 . 
 MutateOperations 
 . 
 Add 
 ( 
 adGroupOperation 
 ); 
  
 mutateGoogleAdsRequest 
 . 
 MutateOperations 
 . 
 Add 
 ( 
 adGroupAdOperation 
 ); 
  
 MutateGoogleAdsResponse 
  
 response 
  
 = 
  
 googleAdsServiceClient 
 . 
 Mutate 
 ( 
 mutateGoogleAdsRequest 
 ); 
  
 PrintResponseDetails 
 ( 
 response 
 ); 
  
 } 
  
 catch 
  
 ( 
 GoogleAdsException 
  
 e 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 "Failure:" 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Message: {e.Message}" 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Failure: {e.Failure}" 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Request ID: {e.RequestId}" 
 ); 
  
 throw 
 ; 
  
 } 
  
 } 
  
 /// <summary> 
  
 /// Retrieves KeywordThemeConstants suggestions with the SmartCampaignSuggestService. 
  
 /// </summary> 
  
 /// <param name="client">The Google Ads client.</param> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <param name="suggestionInfo">The suggestion information.</param> 
  
 /// <returns>The suggestions.</returns> 
  
 private 
  
 List<KeywordThemeConstant> 
  
 GetKeywordThemeSuggestions 
 ( 
  
 GoogleAdsClient 
  
 client 
 , 
  
 long 
  
 customerId 
 , 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
 ) 
  
 { 
  
 SmartCampaignSuggestServiceClient 
  
 smartCampaignSuggestService 
  
 = 
  
 client 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 SmartCampaignSuggestService 
 ); 
  
 SuggestKeywordThemesRequest 
  
 request 
  
 = 
  
 new 
  
 SuggestKeywordThemesRequest 
 () 
  
 { 
  
 SuggestionInfo 
  
 = 
  
 suggestionInfo 
 , 
  
 CustomerId 
  
 = 
  
 customerId 
 . 
 ToString 
 () 
  
 }; 
  
 SuggestKeywordThemesResponse 
  
 response 
  
 = 
  
 smartCampaignSuggestService 
 . 
 SuggestKeywordThemes 
 ( 
 request 
 ); 
  
 // Prints some information about the result. 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Retrieved {response.KeywordThemes.Count} keyword theme " 
  
 + 
  
 $"constant suggestions from the SuggestKeywordThemes method." 
 ); 
  
 return 
  
 response 
 . 
 KeywordThemes 
 . 
 ToList 
 (). 
 ConvertAll 
 ( 
 x 
  
 = 
>  
 x 
 . 
 KeywordThemeConstant 
 ); 
  
 } 
  
 /// <summary> 
  
 /// Retrieves KeywordThemeConstants that are derived from autocomplete data for the 
  
 /// given keyword text. 
  
 /// </summary> 
  
 /// <param name="client">The Google Ads client.</param> 
  
 /// <param name="keywordText">A keyword used for generating keyword auto completions. 
  
 /// </param> 
  
 /// <returns>A list of KeywordThemeConstants.</returns> 
  
 private 
  
 IEnumerable<KeywordThemeConstant> 
  
 GetKeywordTextAutoCompletions 
 ( 
  
 GoogleAdsClient 
  
 client 
 , 
  
 string 
  
 keywordText 
 ) 
  
 { 
  
 KeywordThemeConstantServiceClient 
  
 keywordThemeConstantServiceClient 
  
 = 
  
 client 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 KeywordThemeConstantService 
 ); 
  
 SuggestKeywordThemeConstantsRequest 
  
 request 
  
 = 
  
 new 
  
 SuggestKeywordThemeConstantsRequest 
  
 { 
  
 QueryText 
  
 = 
  
 keywordText 
 , 
  
 CountryCode 
  
 = 
  
 COUNTRY_CODE 
 , 
  
 LanguageCode 
  
 = 
  
 LANGUAGE_CODE 
  
 }; 
  
 SuggestKeywordThemeConstantsResponse 
  
 response 
  
 = 
  
 keywordThemeConstantServiceClient 
 . 
 SuggestKeywordThemeConstants 
 ( 
 request 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Retrieved {response.KeywordThemeConstants.Count} keyword theme " 
  
 + 
  
 $"constants using the keyword '{keywordText}'." 
 ); 
  
 return 
  
 response 
 . 
 KeywordThemeConstants 
 . 
 ToList 
 (); 
  
 } 
  
 /// <summary> 
  
 /// Builds a SmartCampaignSuggestionInfo object with business details. 
  
 /// 
  
 /// The details are used by the SmartCampaignSuggestService to suggest a 
  
 /// budget amount as well as creatives for the ad. 
  
 /// 
  
 /// Note that when retrieving ad creative suggestions it's required that the 
  
 /// "final_url", "language_code" and "keyword_themes" fields are set on the 
  
 /// SmartCampaignSuggestionInfo instance. 
  
 /// </summary> 
  
 /// <param name="client">The Google Ads client.</param> 
  
 /// <param name="businessProfileLocation">The identifier of a Business Profile location. 
  
 /// </param> 
  
 /// <param name="businessName">The name of a Business Profile.</param> 
  
 /// <returns>A SmartCampaignSuggestionInfo instance .</returns> 
  
 private 
  
 SmartCampaignSuggestionInfo 
  
 GetSmartCampaignSuggestionInfo 
 ( 
 GoogleAdsClient 
  
 client 
 , 
  
 string 
  
 businessProfileLocation 
 , 
  
 string 
  
 businessName 
 ) 
  
 { 
  
 // Note: This is broken since businessLocationId is not yet renamed in 
  
 // SmartCampaignSuggestionInfo. The use of dynamic temporarily fixes the broken build. 
  
 // TODO(Anash): Revert the type change once this field is fixed. 
  
 dynamic 
  
 suggestionInfo 
  
 = 
  
 new 
  
 SmartCampaignSuggestionInfo 
  
 { 
  
 // Add the URL of the campaign's landing page. 
  
 FinalUrl 
  
 = 
  
 LANDING_PAGE_URL 
 , 
  
 LanguageCode 
  
 = 
  
 LANGUAGE_CODE 
 , 
  
 // Construct location information using the given geo target constant. It's 
  
 // also possible to provide a geographic proximity using the "proximity" 
  
 // field on suggestion_info, for example: 
  
 // Proximity = new ProximityInfo 
  
 // { 
  
 //     Address = new AddressInfo 
  
 //     { 
  
 //         PostalCode = "INSERT_POSTAL_CODE", 
  
 //         ProvinceCode = "INSERT_PROVINCE_CODE", 
  
 //         CountryCode = "INSERT_COUNTRY_CODE", 
  
 //         ProvinceName = "INSERT_PROVINCE_NAME", 
  
 //         StreetAddress = "INSERT_STREET_ADDRESS", 
  
 //         StreetAddress2 = "INSERT_STREET_ADDRESS_2", 
  
 //         CityName = "INSERT_CITY_NAME" 
  
 //     }, 
  
 //     Radius = Double.Parse("INSERT_RADIUS"), 
  
 //     RadiusUnits = ProximityRadiusUnits.Kilometers 
  
 // } 
  
 // For more information on proximities see: 
  
 // https://developers.google.com/google-ads/api/reference/rpc/latest/ProximityInfo 
  
 LocationList 
  
 = 
  
 new 
  
 LocationList 
 () 
  
 { 
  
 Locations 
  
 = 
  
 { 
  
 new 
  
 LocationInfo 
  
 { 
  
 // Set the location to the resource name of the given geo target 
  
 // constant. 
  
 GeoTargetConstant 
  
 = 
  
 ResourceNames 
 . 
 GeoTargetConstant 
 ( 
 GEO_TARGET_CONSTANT 
 ) 
  
 } 
  
 } 
  
 } 
  
 }; 
  
 // Add the Business Profile location if provided. 
  
 if 
  
 ( 
 ! 
 string 
 . 
 IsNullOrEmpty 
 ( 
 businessProfileLocation 
 )) 
  
 { 
  
 suggestionInfo 
 . 
 BusinessProfileLocation 
  
 = 
  
 businessProfileLocation 
 ; 
  
 } 
  
 else 
  
 { 
  
 suggestionInfo 
 . 
 BusinessContext 
  
 = 
  
 new 
  
 BusinessContext 
  
 { 
  
 BusinessName 
  
 = 
  
 businessName 
 , 
  
 }; 
  
 } 
  
 // Add a schedule detailing which days of the week the business is open. This schedule 
  
 // describes a business that is open on Mondays from 9:00 AM to 5:00 PM. 
  
 AdScheduleInfo 
  
 adScheduleInfo 
  
 = 
  
 new 
  
 AdScheduleInfo 
  
 { 
  
 // Set the day of this schedule as Monday. 
  
 DayOfWeek 
  
 = 
  
 DayOfWeekEnum 
 . 
 Types 
 . 
 DayOfWeek 
 . 
 Monday 
 , 
  
 // Set the start hour to 9 AM. 
  
 StartHour 
  
 = 
  
 9 
 , 
  
 // Set the end hour to 5 PM. 
  
 EndHour 
  
 = 
  
 17 
 , 
  
 // Set the start and end minutes to zero. 
  
 StartMinute 
  
 = 
  
 MinuteOfHourEnum 
 . 
 Types 
 . 
 MinuteOfHour 
 . 
 Zero 
 , 
  
 EndMinute 
  
 = 
  
 MinuteOfHourEnum 
 . 
 Types 
 . 
 MinuteOfHour 
 . 
 Zero 
  
 }; 
  
 suggestionInfo 
 . 
 AdSchedules 
 . 
 Add 
 ( 
 adScheduleInfo 
 ); 
  
 return 
  
 suggestionInfo 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Retrieves a suggested budget amount for a new budget. 
  
 /// Using the SmartCampaignSuggestService to determine a daily budget for new and existing 
  
 /// Smart campaigns is highly recommended because it helps the campaigns achieve optimal 
  
 /// performance. 
  
 /// </summary> 
  
 /// <param name="client">The Google Ads client.</param> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <param name="suggestionInfo"></param> 
  
 /// <returns>A daily budget amount in micros.</returns> 
  
 private 
  
 long 
  
 GetBudgetSuggestion 
 ( 
 GoogleAdsClient 
  
 client 
 , 
  
 long 
  
 customerId 
 , 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
 ) 
  
 { 
  
 SmartCampaignSuggestServiceClient 
  
 smartCampaignSuggestServiceClient 
  
 = 
  
 client 
 . 
 GetService 
  
 ( 
 Services 
 . 
 V21 
 . 
 SmartCampaignSuggestService 
 ); 
  
 SuggestSmartCampaignBudgetOptionsRequest 
  
 request 
  
 = 
  
 new 
  
 SuggestSmartCampaignBudgetOptionsRequest 
  
 { 
  
 CustomerId 
  
 = 
  
 customerId 
 . 
 ToString 
 (), 
  
 // You can retrieve suggestions for an existing campaign by setting the 
  
 // "Campaign" field of the request to the resource name of a campaign and 
  
 // leaving the rest of the request fields below unset: 
  
 // Campaign = "INSERT_CAMPAIGN_RESOURCE_NAME_HERE", 
  
 // Since these suggestions are for a new campaign, we're going to use the 
  
 // SuggestionInfo field instead. 
  
 SuggestionInfo 
  
 = 
  
 suggestionInfo 
 , 
  
 }; 
  
 LocationInfo 
  
 locationInfo 
  
 = 
  
 new 
  
 LocationInfo 
  
 { 
  
 // Set the location to the resource name of the given geo target constant. 
  
 GeoTargetConstant 
  
 = 
  
 ResourceNames 
 . 
 GeoTargetConstant 
 ( 
 GEO_TARGET_CONSTANT 
 ) 
  
 }; 
  
 // Issue a request to retrieve a budget suggestion. 
  
 SuggestSmartCampaignBudgetOptionsResponse 
  
 response 
  
 = 
  
 smartCampaignSuggestServiceClient 
 . 
 SuggestSmartCampaignBudgetOptions 
 ( 
 request 
 ); 
  
 // Three tiers of options will be returned: "low", "high", and "recommended". 
  
 // Here we will use the "recommended" option. The amount is specified in micros, where 
  
 // one million is equivalent to one currency unit. 
  
 Console 
 . 
 WriteLine 
 ( 
 $"A daily budget amount of " 
  
 + 
  
 $"{response.Recommended.DailyAmountMicros}" 
  
 + 
  
 $" was suggested, garnering an estimated minimum of " 
  
 + 
  
 $"{response.Recommended.Metrics.MinDailyClicks} clicks and an estimated " 
  
 + 
  
 $"maximum of {response.Recommended.Metrics.MaxDailyClicks} clicks per day." 
 ); 
  
 return 
  
 response 
 . 
 Recommended 
 . 
 DailyAmountMicros 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Retrieves creative suggestions for a Smart campaign ad. 
  
 /// 
  
 /// Using the SmartCampaignSuggestService to suggest creatives for new 
  
 /// and existing Smart campaigns is highly recommended because it helps 
  
 /// the campaigns achieve optimal performance. 
  
 /// </summary> 
  
 /// <param name="client"></param> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <param name="suggestionInfo">a SmartCampaignSuggestionInfo instance 
  
 /// with details about the business being advertised.</param> 
  
 /// <returns>A SmartCampaignAdInfo instance with suggested headlines and 
  
 /// descriptions.</returns> 
  
 private 
  
 SmartCampaignAdInfo 
  
 GetAdSuggestions 
 ( 
 GoogleAdsClient 
  
 client 
 , 
  
 long 
  
 customerId 
 , 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
 ) 
  
 { 
  
 SmartCampaignSuggestServiceClient 
  
 smartCampaignSuggestService 
  
 = 
  
 client 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 SmartCampaignSuggestService 
 ); 
  
 SuggestSmartCampaignAdRequest 
  
 request 
  
 = 
  
 new 
  
 SuggestSmartCampaignAdRequest 
  
 { 
  
 CustomerId 
  
 = 
  
 customerId 
 . 
 ToString 
 (), 
  
 // Unlike the SuggestSmartCampaignBudgetOptions method, it's only possible to 
  
 // use suggestion_info to retrieve ad creative suggestions. 
  
 SuggestionInfo 
  
 = 
  
 suggestionInfo 
  
 }; 
  
 // Issue a request to retrieve ad creative suggestions. 
  
 SuggestSmartCampaignAdResponse 
  
 response 
  
 = 
  
 smartCampaignSuggestService 
 . 
 SuggestSmartCampaignAd 
 ( 
 request 
 ); 
  
 // The SmartCampaignAdInfo object in the response contains a list of up to 
  
 // three headlines and two descriptions. Note that some of the suggestions 
  
 // may have empty strings as text. Before setting these on the ad you should 
  
 // review them and filter out any empty values. 
  
 SmartCampaignAdInfo 
  
 adSuggestions 
  
 = 
  
 response 
 . 
 AdInfo 
 ; 
  
 if 
  
 ( 
 adSuggestions 
  
 != 
  
 null 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 $"The following headlines were suggested:" 
 ); 
  
 foreach 
  
 ( 
 AdTextAsset 
  
 headline 
  
 in 
  
 adSuggestions 
 . 
 Headlines 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 $"\t{headline.Text}" 
 ); 
  
 } 
  
 Console 
 . 
 WriteLine 
 ( 
 $"And the following descriptions were suggested:" 
 ); 
  
 foreach 
  
 ( 
 AdTextAsset 
  
 description 
  
 in 
  
 adSuggestions 
 . 
 Descriptions 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 $"\t{description.Text}" 
 ); 
  
 } 
  
 } 
  
 else 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 "No ad suggestions were found." 
 ); 
  
 adSuggestions 
  
 = 
  
 new 
  
 SmartCampaignAdInfo 
 (); 
  
 } 
  
 return 
  
 adSuggestions 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Creates a MutateOperation that creates a new CampaignBudget. 
  
 /// A temporary ID will be assigned to this campaign budget so that it can be referenced by 
  
 /// other objects being created in the same Mutate request. 
  
 /// </summary> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <param name="suggestedBudgetAmount">A daily amount budget in micros.</param> 
  
 /// <returns>A MutateOperation that creates a CampaignBudget</returns> 
  
 private 
  
 MutateOperation 
  
 CreateCampaignBudgetOperation 
 ( 
 long 
  
 customerId 
 , 
  
 long 
  
 suggestedBudgetAmount 
 ) 
  
 { 
  
 return 
  
 new 
  
 MutateOperation 
  
 { 
  
 CampaignBudgetOperation 
  
 = 
  
 new 
  
 CampaignBudgetOperation 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 CampaignBudget 
  
 { 
  
 Name 
  
 = 
  
 $"Smart campaign budget #{ExampleUtilities.GetRandomString()}" 
 , 
  
 // A budget used for Smart campaigns must have the type SMART_CAMPAIGN. 
  
 Type 
  
 = 
  
 BudgetType 
 . 
 SmartCampaign 
 , 
  
 // The suggested budget amount from the SmartCampaignSuggestService is a 
  
 // daily budget. We don't need to specify that here, because the budget 
  
 // period already defaults to DAILY. 
  
 AmountMicros 
  
 = 
  
 suggestedBudgetAmount 
 , 
  
 // Set a temporary ID in the budget's resource name so it can be referenced 
  
 // by the campaign in later steps. 
  
 ResourceName 
  
 = 
  
 ResourceNames 
 . 
 CampaignBudget 
 ( 
  
 customerId 
 , 
  
 BUDGET_TEMPORARY_ID 
 ) 
  
 } 
  
 } 
  
 }; 
  
 } 
  
 /// <summary> 
  
 /// Creates a MutateOperation that creates a new Smart campaign. 
  
 /// A temporary ID will be assigned to this campaign so that it can be referenced by other 
  
 /// objects being created in the same Mutate request. 
  
 /// </summary> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <returns>A MutateOperation that creates a campaign.</returns> 
  
 private 
  
 MutateOperation 
  
 CreateSmartCampaignOperation 
 ( 
 long 
  
 customerId 
 ) 
  
 { 
  
 return 
  
 new 
  
 MutateOperation 
  
 { 
  
 CampaignOperation 
  
 = 
  
 new 
  
 CampaignOperation 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 Campaign 
  
 { 
  
 Name 
  
 = 
  
 $"Smart campaign #{ExampleUtilities.GetRandomString()}" 
 , 
  
 // Set the campaign status as PAUSED. The campaign is the only entity in 
  
 // the mutate request that should have its status set. 
  
 Status 
  
 = 
  
 CampaignStatus 
 . 
 Paused 
 , 
  
 // AdvertisingChannelType must be SMART. 
  
 AdvertisingChannelType 
  
 = 
  
 AdvertisingChannelType 
 . 
 Smart 
 , 
  
 // AdvertisingChannelSubType must be SMART_CAMPAIGN. 
  
 AdvertisingChannelSubType 
  
 = 
  
 AdvertisingChannelSubType 
 . 
 SmartCampaign 
 , 
  
 // Assign the resource name with a temporary ID. 
  
 ResourceName 
  
 = 
  
 ResourceNames 
 . 
 Campaign 
 ( 
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ), 
  
 // Set the budget using the given budget resource name. 
  
 CampaignBudget 
  
 = 
  
 ResourceNames 
 . 
 CampaignBudget 
 ( 
 customerId 
 , 
  
 BUDGET_TEMPORARY_ID 
 ), 
  
 // Declare whether or not this campaign contains political ads targeting the EU. 
  
 ContainsEuPoliticalAdvertising 
  
 = 
  
 EuPoliticalAdvertisingStatus 
 . 
 DoesNotContainEuPoliticalAdvertising 
 , 
  
 } 
  
 } 
  
 }; 
  
 } 
  
 /// <summary> 
  
 /// Creates a MutateOperation to create a new SmartCampaignSetting. SmartCampaignSettings 
  
 /// are unique in that they only support UPDATE operations, which are used to update and 
  
 /// create them. Below we will use a temporary ID in the resource name to associate it with 
  
 /// the campaign created in the previous step. 
  
 /// </summary> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <param name="businessProfileLocation">The identifier of a Business Profile location.</param> 
  
 /// <param name="businessName">The name of a Business Profile business.</param> 
  
 /// <returns>A MutateOperation that creates a SmartCampaignSetting.</returns> 
  
 private 
  
 MutateOperation 
  
 CreateSmartCampaignSettingOperation 
 ( 
 long 
  
 customerId 
 , 
  
 string 
  
 businessProfileLocation 
 , 
  
 string 
  
 businessName 
 ) 
  
 { 
  
 SmartCampaignSetting 
  
 smartCampaignSetting 
  
 = 
  
 new 
  
 SmartCampaignSetting 
  
 { 
  
 // Set a temporary ID in the campaign setting's resource name to associate it with 
  
 // the campaign created in the previous step. 
  
 ResourceName 
  
 = 
  
 ResourceNames 
 . 
 SmartCampaignSetting 
 ( 
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ), 
  
 // Below we configure the SmartCampaignSetting using many of the same details used 
  
 // to generate a budget suggestion. 
  
 PhoneNumber 
  
 = 
  
 new 
  
 SmartCampaignSetting 
 . 
 Types 
 . 
 PhoneNumber 
  
 { 
  
 CountryCode 
  
 = 
  
 COUNTRY_CODE 
 , 
  
 PhoneNumber_ 
  
 = 
  
 PHONE_NUMBER 
  
 }, 
  
 FinalUrl 
  
 = 
  
 LANDING_PAGE_URL 
 , 
  
 AdvertisingLanguageCode 
  
 = 
  
 LANGUAGE_CODE 
  
 }; 
  
 // Either a business profile location or a business name must be added to the 
  
 // SmartCampaignSetting. 
  
 if 
  
 ( 
 ! 
 string 
 . 
 IsNullOrEmpty 
 ( 
 businessProfileLocation 
 )) 
  
 { 
  
 // Transform Google Business Location ID to a compatible format before 
  
 // passing it onto the API. 
  
 smartCampaignSetting 
 . 
 BusinessProfileLocation 
  
 = 
  
 businessProfileLocation 
 ; 
  
 } 
  
 else 
  
 { 
  
 smartCampaignSetting 
 . 
 BusinessName 
  
 = 
  
 businessName 
 ; 
  
 } 
  
 return 
  
 new 
  
 MutateOperation 
  
 { 
  
 SmartCampaignSettingOperation 
  
 = 
  
 new 
  
 SmartCampaignSettingOperation 
  
 { 
  
 Update 
  
 = 
  
 smartCampaignSetting 
 , 
  
 // Set the update mask on the operation. This is required since the smart 
  
 // campaign setting is created in an UPDATE operation. Here the update mask 
  
 // will be a list of all the fields that were set on the SmartCampaignSetting. 
  
 UpdateMask 
  
 = 
  
 FieldMasks 
 . 
 AllSetFieldsOf 
 ( 
 smartCampaignSetting 
 ) 
  
 } 
  
 }; 
  
 } 
  
 /// <summary> 
  
 /// Creates a list of MutateOperations that create new campaign criteria. 
  
 /// </summary> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <param name="keywordThemeInfos">A list of KeywordThemeInfos.</param> 
  
 /// <param name="suggestionInfo">A SmartCampaignSuggestionInfo instance.</param> 
  
 /// <returns>A list of MutateOperations that create new campaign criteria.</returns> 
  
 private 
  
 IEnumerable<MutateOperation> 
  
 CreateCampaignCriterionOperations 
 ( 
 long 
  
 customerId 
 , 
  
 IEnumerable<KeywordThemeInfo> 
  
 keywordThemeInfos 
 , 
  
 SmartCampaignSuggestionInfo 
  
 suggestionInfo 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 mutateOperations 
  
 = 
  
 keywordThemeInfos 
 . 
 Select 
 ( 
  
 keywordThemeInfo 
  
 = 
>  
 new 
  
 MutateOperation 
  
 { 
  
 CampaignCriterionOperation 
  
 = 
  
 new 
  
 CampaignCriterionOperation 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 CampaignCriterion 
  
 { 
  
 // Set the campaign ID to a temporary ID. 
  
 Campaign 
  
 = 
  
 ResourceNames 
 . 
 Campaign 
 ( 
  
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ), 
  
 // Set the keyword theme to each KeywordThemeInfo in turn. 
  
 KeywordTheme 
  
 = 
  
 keywordThemeInfo 
 , 
  
 } 
  
 } 
  
 }). 
 ToList 
 (); 
  
 // Create a location criterion for each location in the suggestion info. 
  
 mutateOperations 
 . 
 AddRange 
 ( 
  
 suggestionInfo 
 . 
 LocationList 
 . 
 Locations 
 . 
 Select 
 ( 
  
 locationInfo 
  
 = 
>  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 CampaignCriterionOperation 
  
 = 
  
 new 
  
 CampaignCriterionOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 CampaignCriterion 
 () 
  
 { 
  
 // Set the campaign ID to a temporary ID. 
  
 Campaign 
  
 = 
  
 ResourceNames 
 . 
 Campaign 
 ( 
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ), 
  
 // Set the location to the given location. 
  
 Location 
  
 = 
  
 locationInfo 
  
 } 
  
 } 
  
 }). 
 ToList 
 () 
  
 ); 
  
 return 
  
 mutateOperations 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Creates a MutateOperation that creates a new ad group. 
  
 /// A temporary ID will be used in the campaign resource name for this ad group to 
  
 /// associate it with the Smart campaign created in earlier steps. A temporary ID will 
  
 /// also be used for its own resource name so that we can associate an ad group ad with 
  
 /// it later in the process. 
  
 /// Only one ad group can be created for a given Smart campaign. 
  
 /// </summary> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <returns>A MutateOperation that creates a new ad group.</returns> 
  
 private 
  
 MutateOperation 
  
 CreateAdGroupOperation 
 ( 
 long 
  
 customerId 
 ) 
  
 { 
  
 return 
  
 new 
  
 MutateOperation 
  
 { 
  
 AdGroupOperation 
  
 = 
  
 new 
  
 AdGroupOperation 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AdGroup 
  
 { 
  
 // Set the ad group ID to a temporary ID. 
  
 ResourceName 
  
 = 
  
 ResourceNames 
 . 
 AdGroup 
 ( 
 customerId 
 , 
  
 AD_GROUP_TEMPORARY_ID 
 ), 
  
 Name 
  
 = 
  
 $"Smart campaign ad group #{ExampleUtilities.GetRandomString()}" 
 , 
  
 // Set the campaign ID to a temporary ID. 
  
 Campaign 
  
 = 
  
 ResourceNames 
 . 
 Campaign 
 ( 
 customerId 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ), 
  
 // The ad group type must be SmartCampaignAds. 
  
 Type 
  
 = 
  
 AdGroupType 
 . 
 SmartCampaignAds 
  
 } 
  
 } 
  
 }; 
  
 } 
  
 /// <summary> 
  
 /// Creates a MutateOperation that creates a new ad group ad. 
  
 /// A temporary ID will be used in the ad group resource name for this ad group ad to 
  
 /// associate it with the ad group created in earlier steps. 
  
 /// </summary> 
  
 /// <param name="customerId">The Google Ads customer ID.</param> 
  
 /// <param name="adSuggestions">SmartCampaignAdInfo with ad creative 
  
 /// suggestions.</param> 
  
 /// <returns>A MutateOperation that creates a new ad group ad.</returns> 
  
 private 
  
 MutateOperation 
  
 CreateAdGroupAdOperation 
 ( 
 long 
  
 customerId 
 , 
  
 SmartCampaignAdInfo 
  
 adSuggestions 
 ) 
  
 { 
  
 AdGroupAd 
  
 adGroupAd 
  
 = 
  
 new 
  
 AdGroupAd 
  
 { 
  
 AdGroup 
  
 = 
  
 ResourceNames 
 . 
 AdGroup 
 ( 
 customerId 
 , 
  
 AD_GROUP_TEMPORARY_ID 
 ), 
  
 Ad 
  
 = 
  
 new 
  
 Ad 
  
 { 
  
 SmartCampaignAd 
  
 = 
  
 new 
  
 SmartCampaignAdInfo 
 (), 
  
 }, 
  
 }; 
  
 SmartCampaignAdInfo 
  
 ad 
  
 = 
  
 adGroupAd 
 . 
 Ad 
 . 
 SmartCampaignAd 
 ; 
  
 // The SmartCampaignAdInfo object includes headlines and descriptions 
  
 // retrieved from the SmartCampaignSuggestService.SuggestSmartCampaignAd 
  
 // method. It's recommended that users review and approve or update these 
  
 // creatives before they're set on the ad. It's possible that some or all of 
  
 // these assets may contain empty texts, which should not be set on the ad 
  
 // and instead should be replaced with meaninful texts from the user. Below 
  
 // we just accept the creatives that were suggested while filtering out empty 
  
 // assets. If no headlines or descriptions were suggested, then we manually 
  
 // add some, otherwise this operation will generate an INVALID_ARGUMENT 
  
 // error. Individual workflows will likely vary here. 
  
 ad 
 . 
 Headlines 
 . 
 Add 
 ( 
 adSuggestions 
 . 
 Headlines 
 ); 
  
 ad 
 . 
 Descriptions 
 . 
 Add 
 ( 
 adSuggestions 
 . 
 Descriptions 
 ); 
  
 // If there are fewer headlines than are required, we manually add additional 
  
 // headlines to make up for the difference. 
  
 if 
  
 ( 
 adSuggestions 
 . 
 Headlines 
 . 
 Count 
 () 
 < 
 NUM_REQUIRED_HEADLINES 
 ) 
  
 { 
  
 for 
  
 ( 
 int 
  
 i 
  
 = 
  
 0 
 ; 
  
 i 
 < 
 NUM_REQUIRED_HEADLINES 
  
 - 
  
 adSuggestions 
 . 
 Headlines 
 . 
 Count 
 (); 
  
 i 
 ++ 
 ) 
  
 { 
  
 ad 
 . 
 Headlines 
 . 
 Add 
 ( 
 new 
  
 AdTextAsset 
 () 
  
 { 
  
 Text 
  
 = 
  
 $"Placeholder headline {i + 1}" 
  
 }); 
  
 } 
  
 } 
  
 // If there are fewer descriptions than are required, we manually add 
  
 // additional descriptions to make up for the difference. 
  
 if 
  
 ( 
 adSuggestions 
 . 
 Descriptions 
 . 
 Count 
 () 
 < 
 NUM_REQUIRED_DESCRIPTIONS 
 ) 
  
 { 
  
 for 
  
 ( 
 int 
  
 i 
  
 = 
  
 0 
 ; 
  
 i 
 < 
 NUM_REQUIRED_DESCRIPTIONS 
  
 - 
  
 adSuggestions 
 . 
 Descriptions 
 . 
 Count 
 (); 
  
 i 
 ++ 
 ) 
  
 { 
  
 ad 
 . 
 Descriptions 
 . 
 Add 
 ( 
 new 
  
 AdTextAsset 
 () 
  
 { 
  
 Text 
  
 = 
  
 $"Placeholder description {i + 1}" 
  
 }); 
  
 } 
  
 } 
  
 return 
  
 new 
  
 MutateOperation 
  
 { 
  
 AdGroupAdOperation 
  
 = 
  
 new 
  
 AdGroupAdOperation 
  
 { 
  
 Create 
  
 = 
  
 adGroupAd 
  
 } 
  
 }; 
  
 } 
  
 /// <summary> 
  
 /// Converts the business location ID from the format returned by Business Profile 
  
 /// to the format expected by the API. 
  
 /// </summary> 
  
 /// <param name="businessLocationId">The business location identifier.</param> 
  
 /// <returns>The transformed ID.</returns> 
  
 private 
  
 long 
  
 ConvertBusinessLocationId 
 ( 
 ulong 
  
 businessLocationId 
 ) 
  
 { 
  
 // The business location ID is an unsigned 64-bit integer. However, the Google Ads API 
  
 // expects a signed 64-bit integer. So we convert the unsigned ID into a signed ID, 
  
 // while allowing an overflow, so that the ID wraps around if it is too large. 
  
 return 
  
 unchecked 
 (( 
 long 
 ) 
  
 businessLocationId 
 ); 
  
 } 
  
 /// <summary> 
  
 /// Prints the details of a MutateGoogleAdsResponse. Parses the "response" oneof field name 
  
 /// and uses it to extract the new entity's name and resource name. 
  
 /// </summary> 
  
 /// <param name="response">A MutateGoogleAdsResponse instance.</param> 
  
 private 
  
 void 
  
 PrintResponseDetails 
 ( 
 MutateGoogleAdsResponse 
  
 response 
 ) 
  
 { 
  
 // Parse the Mutate response to print details about the entities that were created 
  
 // in the request. 
  
 foreach 
  
 ( 
 MutateOperationResponse 
  
 operationResponse 
  
 in 
  
 response 
 . 
 MutateOperationResponses 
 ) 
  
 { 
  
 string 
  
 resourceName 
  
 = 
  
 "<not found>" 
 ; 
  
 string 
  
 entityName 
  
 = 
  
 operationResponse 
 . 
 ResponseCase 
 . 
 ToString 
 (); 
  
 // Trim the substring "Result" from the end of the entity name. 
  
 entityName 
  
 = 
  
 entityName 
 . 
 Remove 
 ( 
 entityName 
 . 
 Length 
  
 - 
  
 6 
 ); 
  
 switch 
  
 ( 
 operationResponse 
 . 
 ResponseCase 
 ) 
  
 { 
  
 case 
  
 MutateOperationResponse 
 . 
 ResponseOneofCase 
 . 
 AdGroupResult 
 : 
  
 resourceName 
  
 = 
  
 operationResponse 
 . 
 AdGroupResult 
 . 
 ResourceName 
 ; 
  
 break 
 ; 
  
 case 
  
 MutateOperationResponse 
 . 
 ResponseOneofCase 
 . 
 AdGroupAdResult 
 : 
  
 resourceName 
  
 = 
  
 operationResponse 
 . 
 AdGroupAdResult 
 . 
 ResourceName 
 ; 
  
 break 
 ; 
  
 case 
  
 MutateOperationResponse 
 . 
 ResponseOneofCase 
 . 
 CampaignResult 
 : 
  
 resourceName 
  
 = 
  
 operationResponse 
 . 
 CampaignResult 
 . 
 ResourceName 
 ; 
  
 break 
 ; 
  
 case 
  
 MutateOperationResponse 
 . 
 ResponseOneofCase 
 . 
 CampaignBudgetResult 
 : 
  
 resourceName 
  
 = 
  
 operationResponse 
 . 
 CampaignBudgetResult 
 . 
 ResourceName 
 ; 
  
 break 
 ; 
  
 case 
  
 MutateOperationResponse 
 . 
 ResponseOneofCase 
 . 
 CampaignCriterionResult 
 : 
  
 resourceName 
  
 = 
  
 operationResponse 
 . 
 CampaignCriterionResult 
 . 
 ResourceName 
 ; 
  
 break 
 ; 
  
 case 
  
 MutateOperationResponse 
 . 
 ResponseOneofCase 
 . 
 SmartCampaignSettingResult 
 : 
  
 resourceName 
  
 = 
  
 operationResponse 
 . 
 SmartCampaignSettingResult 
 . 
 ResourceName 
 ; 
  
 break 
 ; 
  
 } 
  
 Console 
 . 
 WriteLine 
 ( 
  
 $"Created a(n) {entityName} with resource name: '{resourceName}'." 
 ); 
  
 } 
  
 } 
  
 } 
 } 
  
  

PHP

< ?php 
 /** 
 * Copyright 2021 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. 
 */ 
 namespace Google\Ads\GoogleAds\Examples\AdvancedOperations; 
 require __DIR__ . '/../../vendor/autoload.php'; 
 use GetOpt\GetOpt; 
 use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames; 
 use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser; 
 use Google\Ads\GoogleAds\Examples\Utils\Helper; 
 use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder; 
 use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClient; 
 use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClientBuilder; 
 use Google\Ads\GoogleAds\Lib\V21\GoogleAdsException; 
 use Google\Ads\GoogleAds\Util\FieldMasks; 
 use Google\Ads\GoogleAds\Util\V21\ResourceNames; 
 use Google\Ads\GoogleAds\V21\Common\AdScheduleInfo; 
 use Google\Ads\GoogleAds\V21\Common\AdTextAsset; 
 use Google\Ads\GoogleAds\V21\Common\KeywordThemeInfo; 
 use Google\Ads\GoogleAds\V21\Common\LocationInfo; 
 use Google\Ads\GoogleAds\V21\Common\SmartCampaignAdInfo; 
 use Google\Ads\GoogleAds\V21\Enums\AdGroupTypeEnum\AdGroupType; 
 use Google\Ads\GoogleAds\V21\Enums\AdTypeEnum\AdType; 
 use Google\Ads\GoogleAds\V21\Enums\AdvertisingChannelSubTypeEnum\AdvertisingChannelSubType; 
 use Google\Ads\GoogleAds\V21\Enums\AdvertisingChannelTypeEnum\AdvertisingChannelType; 
 use Google\Ads\GoogleAds\V21\Enums\BudgetTypeEnum\BudgetType; 
 use Google\Ads\GoogleAds\V21\Enums\CampaignStatusEnum\CampaignStatus; 
 use Google\Ads\GoogleAds\V21\Enums\DayOfWeekEnum\DayOfWeek; 
 use Google\Ads\GoogleAds\V21\Enums\EuPoliticalAdvertisingStatusEnum\EuPoliticalAdvertisingStatus; 
 use Google\Ads\GoogleAds\V21\Enums\MinuteOfHourEnum\MinuteOfHour; 
 use Google\Ads\GoogleAds\V21\Errors\GoogleAdsError; 
 use Google\Ads\GoogleAds\V21\Resources\Ad; 
 use Google\Ads\GoogleAds\V21\Resources\AdGroup; 
 use Google\Ads\GoogleAds\V21\Resources\AdGroupAd; 
 use Google\Ads\GoogleAds\V21\Resources\Campaign; 
 use Google\Ads\GoogleAds\V21\Resources\CampaignBudget; 
 use Google\Ads\GoogleAds\V21\Resources\CampaignCriterion; 
 use Google\Ads\GoogleAds\V21\Resources\KeywordThemeConstant; 
 use Google\Ads\GoogleAds\V21\Resources\SmartCampaignSetting; 
 use Google\Ads\GoogleAds\V21\Resources\SmartCampaignSetting\PhoneNumber; 
 use Google\Ads\GoogleAds\V21\Services\AdGroupAdOperation; 
 use Google\Ads\GoogleAds\V21\Services\AdGroupOperation; 
 use Google\Ads\GoogleAds\V21\Services\CampaignBudgetOperation; 
 use Google\Ads\GoogleAds\V21\Services\CampaignCriterionOperation; 
 use Google\Ads\GoogleAds\V21\Services\CampaignOperation; 
 use Google\Ads\GoogleAds\V21\Services\MutateGoogleAdsRequest; 
 use Google\Ads\GoogleAds\V21\Services\MutateGoogleAdsResponse; 
 use Google\Ads\GoogleAds\V21\Services\MutateOperation; 
 use Google\Ads\GoogleAds\V21\Services\MutateOperationResponse; 
 use Google\Ads\GoogleAds\V21\Services\SmartCampaignSettingOperation; 
 use Google\Ads\GoogleAds\V21\Services\SmartCampaignSuggestionInfo; 
 use Google\Ads\GoogleAds\V21\Services\SmartCampaignSuggestionInfo\BusinessContext; 
 use Google\Ads\GoogleAds\V21\Services\SmartCampaignSuggestionInfo\LocationList; 
 use Google\Ads\GoogleAds\V21\Services\SuggestKeywordThemeConstantsRequest; 
 use Google\Ads\GoogleAds\V21\Services\SuggestKeywordThemesRequest; 
 use Google\Ads\GoogleAds\V21\Services\SuggestKeywordThemesResponse\KeywordTheme; 
 use Google\Ads\GoogleAds\V21\Services\SuggestSmartCampaignAdRequest; 
 use Google\Ads\GoogleAds\V21\Services\SuggestSmartCampaignBudgetOptionsRequest; 
 use Google\ApiCore\ApiException; 
 use InvalidArgumentException; 
 /** 
 * This example adds a Smart campaign. 
 * 
 * More details on Smart campaigns can be found here: 
 * https://support.google.com/google-ads/answer/7652860 
 */ 
 class AddSmartCampaign 
 { 
 private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE'; 
 // Optional: Specify a keyword text used to retrieve keyword theme constant suggestions from the 
 // KeywordThemeConstantService. These keyword theme suggestions are generated using 
 // auto-completion data for the given text and may help improve the performance of the Smart 
 // campaign. 
 private const KEYWORD_TEXT = null; 
 // Optional: A keyword text used to create a free-form keyword theme, which is entirely 
 // user-specified and not derived from any suggestion service. Using free-form keyword themes is 
 // typically not recommended because they are less effective than suggested keyword themes, 
 // however they are useful in situations where a very specific term needs to be targeted. 
 private const FREE_FORM_KEYWORD_TEXT = null; 
 // Optional: Specify the resource name of a Business Profile location. This is required if a 
 // business name is not provided. It can be retrieved using the Business Profile API, see: 
 // https://developers.google.com/my-business/reference/businessinformation/rest/v1/accounts.locations 
 // or from the Business Profile UI (https://support.google.com/business/answer/10737668). 
 private const BUSINESS_PROFILE_LOCATION = null; 
 // Optional: Specify the name of a Business Profile business. This is required if a 
 // business profile location is not provided. 
 private const BUSINESS_NAME = null; 
 // Geo target constant for New York City. 
 private const GEO_TARGET_CONSTANT = '1023191'; 
 // Country code is a two-letter ISO-3166 code, for a list of all codes see: 
 // https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-16 
 private const COUNTRY_CODE = 'US'; 
 // For a list of all language codes, see: 
 // https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 
 private const LANGUAGE_CODE = 'en'; 
 private const LANDING_PAGE_URL = 'http://www.example.com'; 
 private const PHONE_NUMBER = '800-555-0100'; 
 private const BUDGET_TEMPORARY_ID = '-1'; 
 private const SMART_CAMPAIGN_TEMPORARY_ID = '-2'; 
 private const AD_GROUP_TEMPORARY_ID = '-3'; 
 // These define the minimum number of headlines and descriptions that are 
 // required to create an ad group ad in a Smart campaign. 
 private const NUM_REQUIRED_HEADLINES = 3; 
 private const NUM_REQUIRED_DESCRIPTIONS = 2; 
 public static function main() 
 { 
 // Either pass the required parameters for this example on the command line, or insert them 
 // into the constants above. 
 $options = (new ArgumentParser())->parseCommandArguments([ 
 ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT, 
 ArgumentNames::KEYWORD_TEXT => GetOpt::OPTIONAL_ARGUMENT, 
 ArgumentNames::FREE_FORM_KEYWORD_TEXT => GetOpt::OPTIONAL_ARGUMENT, 
 ArgumentNames::BUSINESS_PROFILE_LOCATION => GetOpt::OPTIONAL_ARGUMENT, 
 ArgumentNames::BUSINESS_NAME => GetOpt::OPTIONAL_ARGUMENT 
 ]); 
 $businessProfileLocation = 
 $options[ArgumentNames::BUSINESS_PROFILE_LOCATION] ?: self::BUSINESS_PROFILE_LOCATION; 
 $businessName = $options[ArgumentNames::BUSINESS_NAME] ?: self::BUSINESS_NAME; 
 if ($businessProfileLocation && $businessName) { 
 throw new InvalidArgumentException( 
 'Both the business location resource name and business name are provided but they ' 
 . 'are mutually exclusive. Please only set a value for one of them.' 
 ); 
 } 
 if (!$businessProfileLocation && !$businessName) { 
 throw new InvalidArgumentException( 
 'Neither the business location resource name nor the business name are provided. ' 
 . 'Please set a value for one of them.' 
 ); 
 } 
 // Generate a refreshable OAuth2 credential for authentication. 
 $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build(); 
 // Construct a Google Ads client configured from a properties file and the 
 // OAuth2 credentials above. 
 $googleAdsClient = (new GoogleAdsClientBuilder()) 
 ->fromFile() 
 ->withOAuth2Credential($oAuth2Credential) 
 ->build(); 
 try { 
 self::runExample( 
 $googleAdsClient, 
 $options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID, 
 $options[ArgumentNames::KEYWORD_TEXT] ?: self::KEYWORD_TEXT, 
 $options[ArgumentNames::FREE_FORM_KEYWORD_TEXT] ?: self::FREE_FORM_KEYWORD_TEXT, 
 $businessProfileLocation, 
 $businessName 
 ); 
 } catch (GoogleAdsException $googleAdsException) { 
 printf( 
 "Request with ID '%s' has failed.%sGoogle Ads failure details:%s", 
 $googleAdsException->getRequestId(), 
 PHP_EOL, 
 PHP_EOL 
 ); 
 foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) { 
 /** @var GoogleAdsError $error */ 
 printf( 
 "\t%s: %s%s", 
 $error->getErrorCode()->getErrorCode(), 
 $error->getMessage(), 
 PHP_EOL 
 ); 
 } 
 exit(1); 
 } catch (ApiException $apiException) { 
 printf( 
 "ApiException was thrown with message '%s'.%s", 
 $apiException->getMessage(), 
 PHP_EOL 
 ); 
 exit(1); 
 } 
 } 
 /** 
 * Runs the example. 
 * 
 * @param GoogleAdsClient $googleAdsClient the Google Ads API client 
 * @param int $customerId the customer ID 
 * @param string|null $keywordText a keyword text used for generating keyword themes 
 * @param string|null $freeFormKeywordText a keyword used to create a free-form keyword theme 
 * @param string|null $businessProfileLocationResourceName the resource name of a Business 
 *     Profile location 
 * @param string|null $businessName the name of a Business Profile 
 */ 
 public static function runExample( 
 GoogleAdsClient $googleAdsClient, 
 int $customerId, 
 ?string $keywordText, 
 ?string $freeFormKeywordText, 
 ?string $businessProfileLocationResourceName, 
 ?string $businessName 
 ) { 
 // Gets the SmartCampaignSuggestionInfo object which acts as the basis for many of the 
 // entities necessary to create a Smart campaign. It will be reused a number of times to 
 // retrieve suggestions for keyword themes, budget amount, ads, and campaign criteria. 
 $suggestionInfo = self::getSmartCampaignSuggestionInfo( 
 $businessProfileLocationResourceName, 
 $businessName 
 ); 
 // Generates a list of keyword themes using the SuggestKeywordThemes method on the 
 // SmartCampaignSuggestService. It is strongly recommended that you use this strategy for 
 // generating keyword themes. 
 $keywordThemes = 
 self::getKeywordThemeSuggestions($googleAdsClient, $customerId, $suggestionInfo); 
 // Optionally retrieves auto-complete suggestions for the given keyword text and adds them 
 // to the list of keyword themes. 
 if (!empty($keywordText)) { 
 $keywordThemes = array_merge( 
 $keywordThemes, 
 self::getKeywordTextAutoCompletions($googleAdsClient, $keywordText) 
 ); 
 } 
 // Maps the list of KeywordThemes to KeywordThemeInfos. 
 $keywordThemeInfos = array_map(function (KeywordTheme $keywordTheme) { 
 if ($keywordTheme->getKeywordThemeConstant()) { 
 return new KeywordThemeInfo([ 
 'keyword_theme_constant' => $keywordTheme->getKeywordThemeConstant() 
 ->getResourceName() 
 ]); 
 } elseif ($keywordTheme->getFreeFormKeywordTheme()) { 
 return new KeywordThemeInfo([ 
 'free_form_keyword_theme' => $keywordTheme->getFreeFormKeywordTheme() 
 ]); 
 } else { 
 throw new \UnexpectedValueException( 
 'A malformed KeywordTheme was encountered: ' . $keywordTheme->getKeywordTheme() 
 ); 
 } 
 }, $keywordThemes); 
 // Optionally includes any free-form keywords in verbatim. 
 if (!empty($freeFormKeywordText)) { 
 $keywordThemeInfos[] = 
 new KeywordThemeInfo(['free_form_keyword_theme' => $freeFormKeywordText]); 
 } 
 // Includes the keyword suggestions in the overall SuggestionInfo object. 
 $suggestionInfo = $suggestionInfo->setKeywordThemes($keywordThemeInfos); 
 $suggestedBudgetAmount = self::getBudgetSuggestion( 
 $googleAdsClient, 
 $customerId, 
 $suggestionInfo 
 ); 
 $adSuggestions = self::getAdSuggestions($googleAdsClient, $customerId, $suggestionInfo); 
 // The below methods create and return MutateOperations that we later provide to the 
 // GoogleAdsService.Mutate method in order to create the entities in a single request. 
 // Since the entities for a Smart campaign are closely tied to one-another it's considered 
 // a best practice to create them in a single Mutate request so they all complete 
 // successfully or fail entirely, leaving no orphaned entities. 
 // See: https://developers.google.com/google-ads/api/docs/mutating/overview. 
 $campaignBudgetOperation = self::createCampaignBudgetOperation( 
 $customerId, 
 $suggestedBudgetAmount 
 ); 
 $smartCampaignOperation = self::createSmartCampaignOperation($customerId); 
 $smartCampaignSettingOperation = self::createSmartCampaignSettingOperation( 
 $customerId, 
 $businessProfileLocationResourceName, 
 $businessName 
 ); 
 $campaignCriterionOperations = self::createCampaignCriterionOperations( 
 $customerId, 
 $keywordThemeInfos, 
 $suggestionInfo 
 ); 
 $adGroupOperation = self::createAdGroupOperation($customerId); 
 $adGroupAdOperation = self::createAdGroupAdOperation($customerId, $adSuggestions); 
 // Issues a single mutate request to add the entities. 
 $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); 
 $response = $googleAdsServiceClient->mutate(MutateGoogleAdsRequest::build( 
 $customerId, 
 // It's important to create these entities in this order because they depend on 
 // each other, for example the SmartCampaignSetting and ad group depend on the 
 // campaign, and the ad group ad depends on the ad group. 
 array_merge( 
 [ 
 $campaignBudgetOperation, 
 $smartCampaignOperation, 
 $smartCampaignSettingOperation, 
 ], 
 $campaignCriterionOperations, 
 [ 
 $adGroupOperation, 
 $adGroupAdOperation 
 ] 
 ) 
 )); 
 self::printResponseDetails($response); 
 } 
 /** 
 * Retrieves KeywordThemes using the given suggestion info. 
 * 
 * Here we use the SuggestKeywordThemes method, which uses all of the business details included 
 * in the given SmartCampaignSuggestionInfo instance to generate keyword theme suggestions. This 
 * is the recommended way to generate keyword themes because it uses detailed information about 
 * your business, its location, and website content to generate keyword themes. 
 * 
 * @param GoogleAdsClient $googleAdsClient the Google Ads API client 
 * @param int $customerId the customer ID 
 * @param SmartCampaignSuggestionInfo $suggestionInfo instance with details 
 *     about the business being advertised 
 * @return KeywordTheme[] a list of KeywordThemes 
 */ 
 private static function getKeywordThemeSuggestions( 
 GoogleAdsClient $googleAdsClient, 
 int $customerId, 
 SmartCampaignSuggestionInfo $suggestionInfo 
 ): array { 
 $smartCampaignSuggestServiceClient = 
 $googleAdsClient->getSmartCampaignSuggestServiceClient(); 
 // Issues a request to retrieve the keyword themes. 
 $response = $smartCampaignSuggestServiceClient->suggestKeywordThemes( 
 (new SuggestKeywordThemesRequest()) 
 ->setCustomerId($customerId) 
 ->setSuggestionInfo($suggestionInfo) 
 ); 
 printf( 
 "Retrieved %d keyword theme suggestions from the SuggestKeywordThemes " 
 . "method.%s", 
 $response->getKeywordThemes()->count(), 
 PHP_EOL 
 ); 
 return iterator_to_array($response->getKeywordThemes()->getIterator()); 
 } 
 /** 
 * Retrieves KeywordThemeConstants that are derived from autocomplete data for the given keyword 
 * text. 
 * 
 * These KeywordThemeConstants are derived from autocomplete data for the 
 * given keyword text. They are mapped to KeywordThemes before being returned. 
 * 
 * @param GoogleAdsClient $googleAdsClient the Google Ads API client 
 * @param string $keywordText a keyword text used for generating keyword themes 
 * @return KeywordTheme[] a list of KeywordThemes 
 */ 
 private static function getKeywordTextAutoCompletions( 
 GoogleAdsClient $googleAdsClient, 
 string $keywordText 
 ): array { 
 $keywordThemeConstantService = $googleAdsClient->getKeywordThemeConstantServiceClient(); 
 // Issues a request to retrieve the keyword theme constants. 
 $response = $keywordThemeConstantService->suggestKeywordThemeConstants( 
 (new SuggestKeywordThemeConstantsRequest()) 
 ->setQueryText($keywordText) 
 ->setCountryCode(self::COUNTRY_CODE) 
 ->setLanguageCode(self::LANGUAGE_CODE) 
 ); 
 printf( 
 "Retrieved %d keyword theme constants using the keyword: '%s'.%s", 
 $response->getKeywordThemeConstants()->count(), 
 $keywordText, 
 PHP_EOL 
 ); 
 // Maps the keyword theme constants to KeywordTheme instances for consistency with the 
 // response from SmartCampaignSuggestService.SuggestKeywordThemes. 
 return array_map(function (KeywordThemeConstant $keywordThemeConstant) { 
 return new KeywordTheme([ 
 'keyword_theme_constant' => $keywordThemeConstant 
 ]); 
 }, iterator_to_array($response->getKeywordThemeConstants()->getIterator())); 
 } 
 /** 
 * Builds a SmartCampaignSuggestionInfo object with business details. 
 * 
 * The details are used by the SmartCampaignSuggestService to suggest a budget amount as well 
 * as creatives for the ad. 
 * 
 * Note that when retrieving ad creative suggestions it's required that the "final_url", 
 * "language_code" and "keyword_themes" fields are set on the SmartCampaignSuggestionInfo 
 * instance. 
 * 
 * @param string|null $businessProfileLocationResourceName the resource name of a Business 
 *     Profile location 
 * @param string|null $businessName the name of a Business Profile 
 * @return SmartCampaignSuggestionInfo a SmartCampaignSuggestionInfo instance 
 */ 
 private static function getSmartCampaignSuggestionInfo( 
 ?string $businessProfileLocationResourceName, 
 ?string $businessName 
 ): SmartCampaignSuggestionInfo { 
 $suggestionInfo = new SmartCampaignSuggestionInfo([ 
 // Adds the URL of the campaign's landing page. 
 'final_url' => self::LANDING_PAGE_URL, 
 // Adds the language code for the campaign. 
 'language_code' => self::LANGUAGE_CODE, 
 // Constructs location information using the given geo target constant. It's also 
 // possible to provide a geographic proximity using the "proximity" field, 
 // for example: 
 // 
 // 'proximity' => new ProximityInfo([ 
 //     'address' => mew AddressInfo([ 
 //         'post_code' => INSERT_POSTAL_CODE, 
 //         'province_code' => INSERT_PROVINCE_CODE, 
 //         'country_code' => INSERT_COUNTRY_CODE, 
 //         'province_name' => INSERT_PROVINCE_NAME, 
 //         'street_address' => INSERT_STREET_ADDRESS, 
 //         'street_address2' => INSERT_STREET_ADDRESS_2, 
 //         'city_name' => INSERT_CITY_NAME 
 //     ]), 
 //     'radius' => INSERT_RADIUS, 
 //     'radius_units' => INSERT_RADIUS_UNITS 
 // ]) 
 // 
 // For more information on proximities see: 
 // https://developers.google.com/google-ads/api/reference/rpc/latest/ProximityInfo 
 // Adds LocationInfo objects to the list of locations. You have the option of 
 // providing multiple locations when using location-based suggestions. 
 'location_list' => new LocationList([ 
 // Sets one location to the resource name of the given geo target constant. 
 'locations' => [new LocationInfo([ 
 'geo_target_constant' => ResourceNames::forGeoTargetConstant( 
 self::GEO_TARGET_CONSTANT 
 ) 
 ])] 
 ]), 
 // Adds a schedule detailing which days of the week the business is open. 
 // This schedule describes a schedule in which the business is open on 
 // Mondays from 9am to 5pm. 
 'ad_schedules' => [new AdScheduleInfo([ 
 // Sets the day of this schedule as Monday. 
 'day_of_week' => DayOfWeek::MONDAY, 
 // Sets the start hour to 9am. 
 'start_hour' => 9, 
 // Sets the end hour to 5pm. 
 'end_hour' => 17, 
 // Sets the start and end minute of zero, for example: 9:00 and 5:00. 
 'start_minute' => MinuteOfHour::ZERO, 
 'end_minute' => MinuteOfHour::ZERO 
 ])] 
 ]); 
 // Sets either of the business_profile_location or business_name, depending on whichever is 
 // provided. 
 if ($businessProfileLocationResourceName) { 
 $suggestionInfo->setBusinessProfileLocation($businessProfileLocationResourceName); 
 } else { 
 $suggestionInfo->setBusinessContext(new BusinessContext([ 
 'business_name' => $businessName 
 ])); 
 } 
 return $suggestionInfo; 
 } 
 /** 
 * Retrieves a suggested budget amount for a new budget. 
 * 
 * Using the SmartCampaignSuggestService to determine a daily budget for new and existing 
 * Smart campaigns is highly recommended because it helps the campaigns achieve optimal 
 * performance. 
 * 
 * @param GoogleAdsClient $googleAdsClient the Google Ads API client 
 * @param int $customerId the customer ID 
 * @param SmartCampaignSuggestionInfo $suggestionInfo a SmartCampaignSuggestionInfo instance 
 *      with details about the business being advertised 
 * @return int a daily budget amount in micros 
 */ 
 private static function getBudgetSuggestion( 
 GoogleAdsClient $googleAdsClient, 
 int $customerId, 
 SmartCampaignSuggestionInfo $suggestionInfo 
 ): int { 
 // Issues a request to retrieve a budget suggestion. 
 $smartCampaignSuggestService = $googleAdsClient->getSmartCampaignSuggestServiceClient(); 
 $response = $smartCampaignSuggestService->suggestSmartCampaignBudgetOptions( 
 (new SuggestSmartCampaignBudgetOptionsRequest()) 
 ->setCustomerId($customerId) 
 // You can retrieve suggestions for an existing campaign by setting the "campaign" 
 // field equal to the resource name of a campaign: 
 // ->setCampaign('INSERT_CAMPAIGN_RESOURCE_NAME_HERE'); 
 // Since these suggestions are for a new campaign, we're going to use the 
 // suggestion_info field instead. 
 ->setSuggestionInfo($suggestionInfo) 
 ); 
 // Three tiers of options will be returned, a "low", "high" and "recommended". Here we will 
 // use the "recommended" option. The amount is specified in micros, where one million is 
 // equivalent to one currency unit. 
 $recommendation = $response->getRecommended(); 
 printf( 
 "A daily budget amount of %d micros was suggested, garnering an estimated minimum of " 
 . "%d clicks and an estimated maximum of %d per day.%s", 
 $recommendation->getDailyAmountMicros(), 
 $recommendation->getMetrics()->getMinDailyClicks(), 
 $recommendation->getMetrics()->getMaxDailyClicks(), 
 PHP_EOL 
 ); 
 return $recommendation->getDailyAmountMicros(); 
 } 
 /** 
 * Retrieves creative suggestions for a Smart campaign ad. 
 * 
 * Using the SmartCampaignSuggestService to suggest creatives for new and existing Smart 
 * campaigns is highly recommended because it helps the campaigns achieve optimal performance. 
 * 
 * @param GoogleAdsClient $googleAdsClient the Google Ads API client 
 * @param int $customerId the customer ID 
 * @param SmartCampaignSuggestionInfo $suggestionInfo a SmartCampaignSuggestionInfo instance 
 *      with details about the business being advertised 
 * @return SmartCampaignAdInfo|null a SmartCampaignAdInfo instance with suggested headlines and 
 *      descriptions 
 */ 
 private static function getAdSuggestions( 
 GoogleAdsClient $googleAdsClient, 
 int $customerId, 
 SmartCampaignSuggestionInfo $suggestionInfo 
 ) { 
 // Unlike the SuggestSmartCampaignBudgetOptions method, it's only possible to use 
 // suggestion_info to retrieve ad creative suggestions. 
 // Issues a request to retrieve ad creative suggestions. 
 $smartCampaignSuggestService = $googleAdsClient->getSmartCampaignSuggestServiceClient(); 
 $response = $smartCampaignSuggestService->suggestSmartCampaignAd( 
 (new SuggestSmartCampaignAdRequest()) 
 ->setCustomerId($customerId) 
 ->setSuggestionInfo($suggestionInfo) 
 ); 
 // The SmartCampaignAdInfo object in the response contains a list of up to three headlines 
 // and two descriptions. Note that some of the suggestions may have empty strings as text. 
 // Before setting these on the ad you should review them and filter out any empty values. 
 $adSuggestions = $response->getAdInfo(); 
 if (is_null($adSuggestions)) { 
 return null; 
 } 
 print 'The following headlines were suggested:' . PHP_EOL; 
 foreach ($adSuggestions->getHeadlines() as $headline) { 
 print "\t" . ($headline->getText() ?: 'None') . PHP_EOL; 
 } 
 print 'And the following descriptions were suggested:' . PHP_EOL; 
 foreach ($adSuggestions->getDescriptions() as $description) { 
 print "\t" . ($description->getText() ?: 'None') . PHP_EOL; 
 } 
 return $adSuggestions; 
 } 
 /** 
 * Creates a MutateOperation that creates a new CampaignBudget. 
 * 
 * A temporary ID will be assigned to this campaign budget so that it can be referenced by 
 * other objects being created in the same Mutate request. 
 * 
 * @param int $customerId the customer ID 
 * @param int $suggestedBudgetAmount a daily budget amount in micros 
 * @return MutateOperation a MutateOperation that creates a CampaignBudget 
 */ 
 private static function createCampaignBudgetOperation( 
 int $customerId, 
 int $suggestedBudgetAmount 
 ): MutateOperation { 
 // Creates the campaign budget object. 
 $campaignBudget = new CampaignBudget([ 
 'name' => "Smart campaign budget #" . Helper::getPrintableDatetime(), 
 // A budget used for Smart campaigns must have the type SMART_CAMPAIGN. 
 'type' => BudgetType::SMART_CAMPAIGN, 
 // The suggested budget amount from the SmartCampaignSuggestService is a daily budget. 
 // We don't need to specify that here, because the budget period already defaults to 
 // DAILY. 
 'amount_micros' => $suggestedBudgetAmount, 
 // Sets a temporary ID in the budget's resource name so it can be referenced by the 
 // campaign in later steps. 
 'resource_name' = 
> ResourceNames::forCampaignBudget($customerId, self::BUDGET_TEMPORARY_ID) 
 ]); 
 // Creates the MutateOperation that creates the campaign budget. 
 return new MutateOperation([ 
 'campaign_budget_operation' => new CampaignBudgetOperation([ 
 'create' => $campaignBudget 
 ]) 
 ]); 
 } 
 /** 
 * Creates a MutateOperation that creates a new Smart campaign. 
 * 
 * A temporary ID will be assigned to this campaign so that it can be referenced by other 
 * objects being created in the same Mutate request. 
 * 
 * @param int $customerId the customer ID 
 * @return MutateOperation a MutateOperation that creates a campaign 
 */ 
 private static function createSmartCampaignOperation(int $customerId): MutateOperation 
 { 
 // Creates the campaign object. 
 $campaign = new Campaign([ 
 'name' => "Smart campaign #" . Helper::getPrintableDatetime(), 
 // Sets the campaign status as PAUSED. The campaign is the only entity in the mutate 
 // request that should have its' status set. 
 'status' => CampaignStatus::PAUSED, 
 // The advertising channel type is required to be SMART. 
 'advertising_channel_type' => AdvertisingChannelType::SMART, 
 // The advertising channel sub type is required to be SMART_CAMPAIGN. 
 'advertising_channel_sub_type' => AdvertisingChannelSubType::SMART_CAMPAIGN, 
 // Assigns the resource name with a temporary ID. 
 'resource_name' = 
> ResourceNames::forCampaign($customerId, self::SMART_CAMPAIGN_TEMPORARY_ID), 
 // Sets the budget using the given budget resource name. 
 'campaign_budget' = 
> ResourceNames::forCampaignBudget($customerId, self::BUDGET_TEMPORARY_ID), 
 // Declare whether or not this campaign serves political ads targeting the EU. 
 'contains_eu_political_advertising' = 
> EuPoliticalAdvertisingStatus::DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING 
 ]); 
 // Creates the MutateOperation that creates the campaign. 
 return new MutateOperation([ 
 'campaign_operation' => new CampaignOperation(['create' => $campaign]) 
 ]); 
 } 
 /** 
 * Creates a MutateOperation to create a new SmartCampaignSetting. 
 * 
 * SmartCampaignSettings are unique in that they only support UPDATE operations, which are 
 * used to update and create them. Below we will use a temporary ID in the resource name to 
 * associate it with the campaign created in the previous step. 
 * 
 * @param int $customerId the customer ID 
 * @param string|null $businessProfileLocationResourceName the resource name of a Business 
 *     Profile location 
 * @param string|null $businessName the name of a Business Profile 
 * @return MutateOperation a MutateOperation that creates a SmartCampaignSetting 
 */ 
 private static function createSmartCampaignSettingOperation( 
 int $customerId, 
 ?string $businessProfileLocationResourceName, 
 ?string $businessName 
 ): MutateOperation { 
 // Creates the smart campaign setting object. 
 $smartCampaignSetting = new SmartCampaignSetting([ 
 // Sets a temporary ID in the campaign setting's resource name to associate it with 
 // the campaign created in the previous step. 
 'resource_name' => ResourceNames::forSmartCampaignSetting( 
 $customerId, 
 self::SMART_CAMPAIGN_TEMPORARY_ID 
 ), 
 // Below we configure the SmartCampaignSetting using many of the same details used to 
 // generate a budget suggestion. 
 'phone_number' => new PhoneNumber([ 
 'country_code' => self::COUNTRY_CODE, 
 'phone_number' => self::PHONE_NUMBER 
 ]), 
 'final_url' => self::LANDING_PAGE_URL, 
 'advertising_language_code' => self::LANGUAGE_CODE, 
 ]); 
 // It's required that either a business profile location resource name or a business name is 
 // added to the SmartCampaignSetting. 
 if ($businessProfileLocationResourceName) { 
 $smartCampaignSetting->setBusinessProfileLocation($businessProfileLocationResourceName); 
 } else { 
 $smartCampaignSetting->setBusinessName($businessName); 
 } 
 // Creates the MutateOperation that creates the smart campaign setting with an update. 
 return new MutateOperation([ 
 'smart_campaign_setting_operation' => new SmartCampaignSettingOperation([ 
 'update' => $smartCampaignSetting, 
 // Sets the update mask on the operation. This is required since the smart campaign 
 // setting is created in an UPDATE operation. Here the update mask will be a list 
 // of all the fields that were set on the SmartCampaignSetting. 
 'update_mask' => FieldMasks::allSetFieldsOf($smartCampaignSetting) 
 ]) 
 ]); 
 } 
 /** 
 * Creates a list of MutateOperations that create new campaign criteria. 
 * 
 * @param int $customerId the customer ID 
 * @param KeywordThemeInfo[] $keywordThemeInfos a list of KeywordThemeInfos 
 * @param SmartCampaignSuggestionInfo $smartCampaignSuggestionInfo a SmartCampaignSuggestionInfo 
 *     instance 
 * @return MutateOperation[] a list of MutateOperations that create new campaign criteria 
 */ 
 private static function createCampaignCriterionOperations( 
 int $customerId, 
 array $keywordThemeInfos, 
 SmartCampaignSuggestionInfo $smartCampaignSuggestionInfo 
 ): array { 
 $operations = []; 
 foreach ($keywordThemeInfos as $info) { 
 // Creates the campaign criterion object. 
 $campaignCriterion = new CampaignCriterion([ 
 // Sets the campaign ID to a temporary ID. 
 'campaign' = 
> ResourceNames::forCampaign($customerId, self::SMART_CAMPAIGN_TEMPORARY_ID), 
 // Sets the keyword theme to the given KeywordThemeInfo. 
 'keyword_theme' => $info 
 ]); 
 // Creates the MutateOperation that creates the campaign criterion and adds it to the 
 // list of operations. 
 $operations[] = new MutateOperation([ 
 'campaign_criterion_operation' => new CampaignCriterionOperation([ 
 'create' => $campaignCriterion 
 ]) 
 ]); 
 } 
 // Create a location criterion for each location in the suggestion info object to add 
 // corresponding location targeting to the Smart campaign. 
 foreach ($smartCampaignSuggestionInfo->getLocationList()->getLocations() as $location) { 
 // Creates the campaign criterion object. 
 $campaignCriterion = new CampaignCriterion([ 
 // Sets the campaign ID to a temporary ID. 
 'campaign' = 
> ResourceNames::forCampaign($customerId, self::SMART_CAMPAIGN_TEMPORARY_ID), 
 // Set the location to the given location. 
 'location' => $location 
 ]); 
 // Creates the MutateOperation that creates the campaign criterion and adds it to the 
 // list of operations. 
 $operations[] = new MutateOperation([ 
 'campaign_criterion_operation' => new CampaignCriterionOperation([ 
 'create' => $campaignCriterion 
 ]) 
 ]); 
 } 
 return $operations; 
 } 
 /** 
 * Creates a MutateOperation that creates a new ad group. 
 * 
 * A temporary ID will be used in the campaign resource name for this ad group to associate 
 * it with the Smart campaign created in earlier steps. A temporary ID will also be used for 
 * its own resource name so that we can associate an ad group ad with it later in the process. 
 * 
 * Only one ad group can be created for a given Smart campaign. 
 * 
 * @param int $customerId the customer ID 
 * @return MutateOperation a MutateOperation that creates a new ad group 
 */ 
 private static function createAdGroupOperation(int $customerId): MutateOperation 
 { 
 // Creates the ad group object. 
 $adGroup = new AdGroup([ 
 // Sets the ad group ID to a temporary ID. 
 'resource_name' => ResourceNames::forAdGroup($customerId, self::AD_GROUP_TEMPORARY_ID), 
 'name' => "Smart campaign ad group #" . Helper::getPrintableDatetime(), 
 // Sets the campaign ID to a temporary ID. 
 'campaign' = 
> ResourceNames::forCampaign($customerId, self::SMART_CAMPAIGN_TEMPORARY_ID), 
 // The ad group type must be set to SMART_CAMPAIGN_ADS. 
 'type' => AdGroupType::SMART_CAMPAIGN_ADS 
 ]); 
 // Creates the MutateOperation that creates the ad group. 
 return new MutateOperation([ 
 'ad_group_operation' => new AdGroupOperation(['create' => $adGroup]) 
 ]); 
 } 
 /** 
 * Creates a MutateOperation that creates a new ad group ad. 
 * 
 * A temporary ID will be used in the ad group resource name for this ad group ad to associate 
 * it with the ad group created in earlier steps. 
 * 
 * @param int $customerId the customer ID 
 * @param SmartCampaignAdInfo|null $adSuggestions a SmartCampaignAdInfo object with ad creative 
 *      suggestions 
 * @return MutateOperation a MutateOperation that creates a new ad group ad 
 */ 
 private static function createAdGroupAdOperation( 
 int $customerId, 
 ?SmartCampaignAdInfo $adSuggestions 
 ): MutateOperation { 
 if (is_null($adSuggestions)) { 
 $smartCampaignAdInfo = new SmartCampaignAdInfo(); 
 } else { 
 // The SmartCampaignAdInfo object includes headlines and descriptions retrieved 
 // from the SmartCampaignSuggestService::SuggestSmartCampaignAd method. It's 
 // recommended that users review and approve or update these creatives before 
 // they're set on the ad. It's possible that some or all of these assets may 
 // contain empty texts, which should not be set on the ad and instead should be 
 // replaced with meaningful texts from the user. Below we just accept the creatives 
 // that were suggested while filtering out empty assets, but individual workflows 
 // will vary here. 
 $smartCampaignAdInfo = new SmartCampaignAdInfo([ 
 'headlines' => array_filter( 
 iterator_to_array($adSuggestions->getHeadlines()->getIterator()), 
 function ($value) { 
 return $value->getText(); 
 } 
 ), 
 'descriptions' => array_filter( 
 iterator_to_array($adSuggestions->getDescriptions()->getIterator()), 
 function ($value) { 
 return $value->getText(); 
 } 
 ) 
 ]); 
 } 
 // Creates the ad group ad object. 
 $adGroupAd = new AdGroupAd([ 
 // Sets the ad group ID to a temporary ID. 
 'ad_group' => ResourceNames::forAdGroup($customerId, self::AD_GROUP_TEMPORARY_ID), 
 'ad' => new Ad([ 
 // Sets the type to SMART_CAMPAIGN_AD. 
 'type' => AdType::SMART_CAMPAIGN_AD, 
 'smart_campaign_ad' => $smartCampaignAdInfo 
 ]) 
 ]); 
 // The SmartCampaignAdInfo object includes headlines and descriptions retrieved from the 
 // SmartCampaignSuggestService.SuggestSmartCampaignAd method. It's recommended that users 
 // review and approve or update these ads before they're set on the ad. It's possible that 
 // some or all of these assets may contain empty texts, which should not be set on the ad 
 // and instead should be replaced with meaningful texts from the user. 
 // Below we just accept the ads that were suggested while filtering out empty assets. 
 // If no headlines or descriptions were suggested, then we manually add some, otherwise 
 // this operation will generate an INVALID_ARGUMENT error. Individual workflows will likely 
 // vary here. 
 $currentHeadlinesCount = $smartCampaignAdInfo->getHeadlines()->count(); 
 for ($i = 0; $i < self::NUM_REQUIRED_HEADLINES - $currentHeadlinesCount; $i++) { 
 $smartCampaignAdInfo->setHeadlines( 
 array_merge( 
 iterator_to_array($smartCampaignAdInfo->getHeadlines()), 
 [new AdTextAsset(['text' => 'Placeholder headline ' . $i])] 
 ) 
 ); 
 } 
 $currentDescriptionsCount = $smartCampaignAdInfo->getDescriptions()->count(); 
 for ($i = 0; $i < self::NUM_REQUIRED_DESCRIPTIONS - $currentDescriptionsCount; $i++) { 
 $smartCampaignAdInfo->setDescriptions( 
 array_merge( 
 iterator_to_array($smartCampaignAdInfo->getDescriptions()), 
 [new AdTextAsset(['text' => 'Placeholder description ' . $i])] 
 ) 
 ); 
 } 
 // Creates the MutateOperation that creates the ad group ad. 
 return new MutateOperation([ 
 'ad_group_ad_operation' => new AdGroupAdOperation(['create' => $adGroupAd]) 
 ]); 
 } 
 /** 
 * Prints the details of a MutateGoogleAdsResponse. 
 * 
 * It only covers the expected types of operation result. 
 * 
 * @param MutateGoogleAdsResponse $response a MutateGoogleAdsResponse object 
 */ 
 private static function printResponseDetails(MutateGoogleAdsResponse $response) 
 { 
 // Parses the Mutate response to print details about the entities that were created by the 
 // request. 
 /** @var MutateOperationResponse $result */ 
 foreach ($response->getMutateOperationResponses() as $result) { 
 $resourceType = "unrecognized"; 
 $resourceName = "not found"; 
 if ($result->hasCampaignBudgetResult()) { 
 $resourceType = "CampaignBudget"; 
 $resourceName = $result->getCampaignBudgetResult()->getResourceName(); 
 } elseif ($result->hasCampaignResult()) { 
 $resourceType = "Campaign"; 
 $resourceName = $result->getCampaignResult()->getResourceName(); 
 } elseif ($result->hasSmartCampaignSettingResult()) { 
 $resourceType = "SmartCampaignSetting"; 
 $resourceName = $result->getSmartCampaignSettingResult()->getResourceName(); 
 } elseif ($result->getAdGroupResult()) { 
 $resourceType = "AdGroup"; 
 $resourceName = $result->getAdGroupResult()->getResourceName(); 
 } elseif ($result->getAdGroupAdResult()) { 
 $resourceType = "AdGroupAd"; 
 $resourceName = $result->getAdGroupAdResult()->getResourceName(); 
 } elseif ($result->getCampaignCriterionResult()) { 
 $resourceType = "CampaignCriterion"; 
 $resourceName = $result->getCampaignCriterionResult()->getResourceName(); 
 } 
 printf( 
 "Created a(n) '%s' entity with resource_name: '%s'.%s", 
 $resourceType, 
 $resourceName, 
 PHP_EOL 
 ); 
 } 
 } 
 } 
 AddSmartCampaign::main(); 
  
  

Python

 #!/usr/bin/env python 
 # Copyright 2021 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 Smart campaign. 
 More details on Smart campaigns can be found here: 
 https://support.google.com/google-ads/answer/7652860 
 """ 
 import 
  
 argparse 
 import 
  
 sys 
 from 
  
 typing 
  
 import 
 List 
 , 
 Optional 
 from 
  
 uuid 
  
 import 
 uuid4 
 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.common.types.ad_type_infos 
  
 import 
 ( 
 SmartCampaignAdInfo 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.common.types.criteria 
  
 import 
 ( 
 AdScheduleInfo 
 , 
 KeywordThemeInfo 
 , 
 LocationInfo 
 , 
 ) 
 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.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.keyword_theme_constant 
  
 import 
 ( 
 KeywordThemeConstant 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.resources.types.smart_campaign_setting 
  
 import 
 ( 
 SmartCampaignSetting 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.ad_group_ad_service 
  
 import 
 ( 
 AdGroupAdOperation 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.ad_group_service 
  
 import 
 ( 
 AdGroupOperation 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.campaign_budget_service 
  
 import 
 ( 
 CampaignBudgetOperation 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.campaign_criterion_service 
  
 import 
 ( 
 CampaignCriterionOperation 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.services.campaign_service 
  
 import 
 ( 
 CampaignServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.enums.types.minute_of_hour 
  
 import 
 ( 
 MinuteOfHourEnum 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.campaign_service 
  
 import 
 ( 
 CampaignOperation 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.services.google_ads_service 
  
 import 
 ( 
 GoogleAdsServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.google_ads_service 
  
 import 
 ( 
 MutateGoogleAdsResponse 
 , 
 MutateOperation 
 , 
 MutateOperationResponse 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.services.keyword_theme_constant_service 
  
 import 
 ( 
 KeywordThemeConstantServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.keyword_theme_constant_service 
  
 import 
 ( 
 SuggestKeywordThemeConstantsRequest 
 , 
 SuggestKeywordThemeConstantsResponse 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.services.smart_campaign_suggest_service 
  
 import 
 ( 
 SmartCampaignSuggestServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.smart_campaign_suggest_service 
  
 import 
 ( 
 SmartCampaignSuggestionInfo 
 , 
 SuggestKeywordThemesResponse 
 , 
 SuggestKeywordThemesRequest 
 , 
 SuggestSmartCampaignAdResponse 
 , 
 SuggestSmartCampaignAdRequest 
 , 
 SuggestSmartCampaignBudgetOptionsResponse 
 , 
 SuggestSmartCampaignBudgetOptionsRequest 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.smart_campaign_setting_service 
  
 import 
 ( 
 SmartCampaignSettingOperation 
 , 
 ) 
 from 
  
 google.api_core 
  
 import 
 protobuf_helpers 
 # Geo target constant for New York City. 
 _GEO_TARGET_CONSTANT 
 = 
 "1023191" 
 # Country code is a two-letter ISO-3166 code, for a list of all codes see: 
 # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-16 
 _COUNTRY_CODE 
 = 
 "US" 
 # For a list of all language codes, see: 
 # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 
 _LANGUAGE_CODE 
 = 
 "en" 
 _LANDING_PAGE_URL 
 = 
 "http://www.example.com" 
 _PHONE_NUMBER 
 = 
 "800-555-0100" 
 _BUDGET_TEMPORARY_ID 
 = 
 "-1" 
 _SMART_CAMPAIGN_TEMPORARY_ID 
 = 
 "-2" 
 _AD_GROUP_TEMPORARY_ID 
 = 
 "-3" 
 # These define the minimum number of headlines and descriptions that are 
 # required to create an AdGroupAd in a Smart campaign. 
 _REQUIRED_NUM_HEADLINES 
 = 
 3 
 _REQUIRED_NUM_DESCRIPTIONS 
 = 
 2 
 def 
  
 main 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 keyword_text 
 : 
 Optional 
 [ 
 str 
 ], 
 free_form_keyword_text 
 : 
 Optional 
 [ 
 str 
 ], 
 business_profile_location 
 : 
 Optional 
 [ 
 str 
 ], 
 business_name 
 : 
 Optional 
 [ 
 str 
 ], 
 ) 
 - 
> None 
 : 
  
 """The main method that creates all necessary entities for the example. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 keyword_text: a keyword used for generating keyword themes. 
 free_form_keyword_text: a keyword used to create a free-form keyword 
 theme. 
 business_profile_location: the ID of a Business Profile location. 
 business_name: the name of a Business Profile. 
 """ 
 # The SmartCampaignSuggestionInfo object acts as the basis for many of the 
 # entities necessary to create a Smart campaign. It will be reused a number 
 # of times to retrieve suggestions for keyword themes, budget amount, 
 # ad creatives, and campaign criteria. 
 suggestion_info 
 : 
 SmartCampaignSuggestionInfo 
 = 
 ( 
 get_smart_campaign_suggestion_info 
 ( 
 client 
 , 
 business_profile_location 
 , 
 business_name 
 ) 
 ) 
 # After creating a SmartCampaignSuggestionInfo object we first use it to 
 # generate a list of keyword themes using the SuggestKeywordThemes method 
 # on the SmartCampaignSuggestService. It is strongly recommended that you 
 # use this strategy for generating keyword themes. 
 keyword_themes 
 : 
 List 
 [ 
 SuggestKeywordThemesResponse 
 . 
 KeywordTheme 
 ] 
 = 
 ( 
 get_keyword_theme_suggestions 
 ( 
 client 
 , 
 customer_id 
 , 
 suggestion_info 
 ) 
 ) 
 # If a keyword text is given, retrieve keyword theme constant suggestions 
 # from the KeywordThemeConstantService, map them to KeywordThemes, and 
 # append them to the existing list. This logic should ideally only be used 
 # if the suggestions from the get_keyword_theme_suggestions function are 
 # insufficient. 
 if 
 keyword_text 
 : 
 keyword_themes 
 . 
 extend 
 ( 
 get_keyword_text_auto_completions 
 ( 
 client 
 , 
 keyword_text 
 ) 
 ) 
 # Map the KeywordThemes retrieved by the previous two steps to 
 # KeywordThemeInfo instances. 
 keyword_theme_infos 
 : 
 List 
 [ 
 KeywordThemeInfo 
 ] 
 = 
 ( 
 map_keyword_themes_to_keyword_infos 
 ( 
 client 
 , 
 keyword_themes 
 ) 
 ) 
 # If a free-form keyword text is given we create a KeywordThemeInfo instance 
 # from it and add it to the existing list. 
 if 
 free_form_keyword_text 
 : 
 keyword_theme_infos 
 . 
 append 
 ( 
 get_free_form_keyword_theme_info 
 ( 
 client 
 , 
 free_form_keyword_text 
 ) 
 ) 
 # Now add the generated keyword themes to the suggestion info instance. 
 suggestion_info 
 . 
 keyword_themes 
 . 
 extend 
 ( 
 keyword_theme_infos 
 ) 
 # Retrieve a budget amount suggestion. 
 suggested_budget_amount 
 : 
 int 
 = 
 get_budget_suggestion 
 ( 
 client 
 , 
 customer_id 
 , 
 suggestion_info 
 ) 
 # Retrieve Smart campaign ad creative suggestions. 
 ad_suggestions 
 : 
 SmartCampaignAdInfo 
 = 
 get_ad_suggestions 
 ( 
 client 
 , 
 customer_id 
 , 
 suggestion_info 
 ) 
 # The below methods create and return MutateOperations that we later 
 # provide to the GoogleAdsService.Mutate method in order to create the 
 # entities in a single request. Since the entities for a Smart campaign 
 # are closely tied to one-another it's considered a best practice to 
 # create them in a single Mutate request so they all complete successfully 
 # or fail entirely, leaving no orphaned entities. See: 
 # https://developers.google.com/google-ads/api/docs/mutating/overview 
 campaign_budget_operation 
 : 
 MutateOperation 
 = 
 ( 
 create_campaign_budget_operation 
 ( 
 client 
 , 
 customer_id 
 , 
 suggested_budget_amount 
 ) 
 ) 
 smart_campaign_operation 
 : 
 MutateOperation 
 = 
 create_smart_campaign_operation 
 ( 
 client 
 , 
 customer_id 
 ) 
 smart_campaign_setting_operation 
 : 
 MutateOperation 
 = 
 ( 
 create_smart_campaign_setting_operation 
 ( 
 client 
 , 
 customer_id 
 , 
 business_profile_location 
 , 
 business_name 
 ) 
 ) 
 campaign_criterion_operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 ( 
 create_campaign_criterion_operations 
 ( 
 client 
 , 
 customer_id 
 , 
 keyword_theme_infos 
 , 
 suggestion_info 
 ) 
 ) 
 ad_group_operation 
 : 
 MutateOperation 
 = 
 create_ad_group_operation 
 ( 
 client 
 , 
 customer_id 
 ) 
 ad_group_ad_operation 
 : 
 MutateOperation 
 = 
 create_ad_group_ad_operation 
 ( 
 client 
 , 
 customer_id 
 , 
 ad_suggestions 
 ) 
 googleads_service 
 : 
 GoogleAdsServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "GoogleAdsService" 
 ) 
 # Send the operations into a single Mutate request. 
 response 
 : 
 MutateGoogleAdsResponse 
 = 
 googleads_service 
 . 
 mutate 
 ( 
 customer_id 
 = 
 customer_id 
 , 
 mutate_operations 
 = 
 [ 
 # It's important to create these entities in this order because 
 # they depend on each other, for example the SmartCampaignSetting 
 # and ad group depend on the campaign, and the ad group ad depends 
 # on the ad group. 
 campaign_budget_operation 
 , 
 smart_campaign_operation 
 , 
 smart_campaign_setting_operation 
 , 
 # Expand the list of campaign criterion operations into the list of 
 # other mutate operations 
 * 
 campaign_criterion_operations 
 , 
 ad_group_operation 
 , 
 ad_group_ad_operation 
 , 
 ], 
 ) 
 print_response_details 
 ( 
 response 
 ) 
 def 
  
 get_keyword_theme_suggestions 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 suggestion_info 
 : 
 SmartCampaignSuggestionInfo 
 , 
 ) 
 - 
> List 
 [ 
 SuggestKeywordThemesResponse 
 . 
 KeywordTheme 
 ]: 
  
 """Retrieves KeywordThemes using the given suggestion info. 
 Here we use the SuggestKeywordThemes method, which uses all of the business 
 details included in the given SmartCampaignSuggestionInfo instance to 
 generate keyword theme suggestions. This is the recommended way to 
 generate keyword themes because it uses detailed information about your 
 business, its location, and website content to generate keyword themes. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 suggestion_info: a SmartCampaignSuggestionInfo instance with details 
 about the business being advertised. 
 Returns: 
 a list of KeywordThemes. 
 """ 
 smart_campaign_suggest_service 
 : 
 SmartCampaignSuggestServiceClient 
 = 
 ( 
 client 
 . 
 get_service 
 ( 
 "SmartCampaignSuggestService" 
 ) 
 ) 
 request 
 : 
 SuggestKeywordThemesRequest 
 = 
 client 
 . 
 get_type 
 ( 
 "SuggestKeywordThemesRequest" 
 ) 
 request 
 . 
 customer_id 
 = 
 customer_id 
 request 
 . 
 suggestion_info 
 = 
 suggestion_info 
 response 
 : 
 SuggestKeywordThemesResponse 
 = 
 ( 
 smart_campaign_suggest_service 
 . 
 suggest_keyword_themes 
 ( 
 request 
 = 
 request 
 ) 
 ) 
 print 
 ( 
 f 
 "Retrieved 
 { 
 len 
 ( 
 response 
 . 
 keyword_themes 
 ) 
 } 
 keyword theme suggestions " 
 "from the SuggestKeywordThemes method." 
 ) 
 return 
 response 
 . 
 keyword_themes 
 def 
  
 get_keyword_text_auto_completions 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 keyword_text 
 : 
 str 
 ) 
 - 
> List 
 [ 
 SuggestKeywordThemesResponse 
 . 
 KeywordTheme 
 ]: 
  
 """Retrieves KeywordThemeConstants for the given keyword text. 
 These KeywordThemeConstants are derived from autocomplete data for the 
 given keyword text. They are mapped to KeywordThemes before being returned. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 keyword_text: a keyword used for generating keyword themes. 
 Returns: 
 a list of KeywordThemes. 
 """ 
 keyword_theme_constant_service 
 : 
 KeywordThemeConstantServiceClient 
 = 
 ( 
 client 
 . 
 get_service 
 ( 
 "KeywordThemeConstantService" 
 ) 
 ) 
 request 
 : 
 SuggestKeywordThemeConstantsRequest 
 = 
 client 
 . 
 get_type 
 ( 
 "SuggestKeywordThemeConstantsRequest" 
 ) 
 request 
 . 
 query_text 
 = 
 keyword_text 
 request 
 . 
 country_code 
 = 
 _COUNTRY_CODE 
 request 
 . 
 language_code 
 = 
 _LANGUAGE_CODE 
 response 
 : 
 SuggestKeywordThemeConstantsResponse 
 = 
 ( 
 keyword_theme_constant_service 
 . 
 suggest_keyword_theme_constants 
 ( 
 request 
 = 
 request 
 ) 
 ) 
 print 
 ( 
 f 
 "Retrieved 
 { 
 len 
 ( 
 response 
 . 
 keyword_theme_constants 
 ) 
 } 
 keyword theme " 
 f 
 "constants using the keyword: ' 
 { 
 keyword_text 
 } 
 '" 
 ) 
 # Map the keyword theme constants to KeywordTheme instances for consistency 
 # with the response from SmartCampaignSuggestService.SuggestKeywordThemes. 
 keyword_themes 
 : 
 List 
 [ 
 SuggestKeywordThemesResponse 
 . 
 KeywordTheme 
 ] 
 = 
 [] 
 keyword_theme_constant 
 : 
 KeywordThemeConstant 
 for 
 keyword_theme_constant 
 in 
 response 
 . 
 keyword_theme_constants 
 : 
 # Note that the SuggestKeywordThemesResponse.KeywordTheme is a nested 
 # type and not the same as the top-level KeywordTheme message. 
 keyword_theme 
 : 
 SuggestKeywordThemesResponse 
 . 
 KeywordTheme 
 = 
 ( 
 client 
 . 
 get_type 
 ( 
 "SuggestKeywordThemesResponse" 
 ) 
 . 
 KeywordTheme 
 () 
 ) 
 keyword_theme 
 . 
 keyword_theme_constant 
 = 
 keyword_theme_constant 
 keyword_themes 
 . 
 append 
 ( 
 keyword_theme 
 ) 
 return 
 keyword_themes 
 def 
  
 get_free_form_keyword_theme_info 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 free_form_keyword_text 
 : 
 str 
 ) 
 - 
> KeywordThemeInfo 
 : 
  
 """Creates a KeywordThemeInfo using the given free-form keyword text. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 free_form_keyword_text: a keyword used to create a free-form keyword 
 theme. 
 Returns: 
 a KeywordThemeInfo instance. 
 """ 
 info 
 : 
 KeywordThemeInfo 
 = 
 client 
 . 
 get_type 
 ( 
 "KeywordThemeInfo" 
 ) 
 info 
 . 
 free_form_keyword_theme 
 = 
 free_form_keyword_text 
 return 
 info 
 def 
  
 map_keyword_themes_to_keyword_infos 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 keyword_themes 
 : 
 List 
 [ 
 SuggestKeywordThemesResponse 
 . 
 KeywordTheme 
 ], 
 ) 
 - 
> List 
 [ 
 KeywordThemeInfo 
 ]: 
  
 """Maps a list of KeywordThemes to KeywordThemeInfos. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 keyword_themes: a list of KeywordThemes. 
 Returns: 
 a list of KeywordThemeInfos. 
 """ 
 infos 
 : 
 List 
 [ 
 KeywordThemeInfo 
 ] 
 = 
 [] 
 keyword_theme 
 : 
 SuggestKeywordThemesResponse 
 . 
 KeywordTheme 
 for 
 keyword_theme 
 in 
 keyword_themes 
 : 
 info 
 : 
 KeywordThemeInfo 
 = 
 client 
 . 
 get_type 
 ( 
 "KeywordThemeInfo" 
 ) 
 # Check if the keyword_theme_constant field is set. 
 if 
 "keyword_theme_constant" 
 in 
 keyword_theme 
 : 
 info 
 . 
 keyword_theme_constant 
 = 
 ( 
 keyword_theme 
 . 
 keyword_theme_constant 
 . 
 resource_name 
 ) 
 infos 
 . 
 append 
 ( 
 info 
 ) 
 # Check if the free_form_keyword_theme field is set. 
 elif 
 "free_form_keyword_theme" 
 in 
 keyword_theme 
 : 
 info 
 . 
 free_form_keyword_theme 
 = 
 keyword_theme 
 . 
 free_form_keyword_theme 
 infos 
 . 
 append 
 ( 
 info 
 ) 
 else 
 : 
 raise 
 ValueError 
 ( 
 f 
 "A malformed KeywordTheme was encountered: 
 { 
 keyword_theme 
 } 
 " 
 ) 
 return 
 infos 
 def 
  
 get_smart_campaign_suggestion_info 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 business_profile_location 
 : 
 Optional 
 [ 
 str 
 ], 
 business_name 
 : 
 Optional 
 [ 
 str 
 ], 
 ) 
 - 
> SmartCampaignSuggestionInfo 
 : 
  
 """Builds a SmartCampaignSuggestionInfo object with business details. 
 The details are used by the SmartCampaignSuggestService to suggest a 
 budget amount as well as creatives for the ad. 
 Note that when retrieving ad creative suggestions it's required that the 
 "final_url", "language_code" and "keyword_themes" fields are set on the 
 SmartCampaignSuggestionInfo instance. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 business_profile_location: the resource name of a Business Profile 
 location. 
 business_name: the name of a Business Profile. 
 Returns: 
 A SmartCampaignSuggestionInfo instance. 
 """ 
 suggestion_info 
 : 
 SmartCampaignSuggestionInfo 
 = 
 client 
 . 
 get_type 
 ( 
 "SmartCampaignSuggestionInfo" 
 ) 
 # Add the URL of the campaign's landing page. 
 suggestion_info 
 . 
 final_url 
 = 
 _LANDING_PAGE_URL 
 # Add the language code for the campaign. 
 suggestion_info 
 . 
 language_code 
 = 
 _LANGUAGE_CODE 
 # Construct location information using the given geo target constant. It's 
 # also possible to provide a geographic proximity using the "proximity" 
 # field on suggestion_info, for example: 
 # 
 # suggestion_info.proximity.address.post_code = INSERT_POSTAL_CODE 
 # suggestion_info.proximity.address.province_code = INSERT_PROVINCE_CODE 
 # suggestion_info.proximity.address.country_code = INSERT_COUNTRY_CODE 
 # suggestion_info.proximity.address.province_name = INSERT_PROVINCE_NAME 
 # suggestion_info.proximity.address.street_address = INSERT_STREET_ADDRESS 
 # suggestion_info.proximity.address.street_address2 = INSERT_STREET_ADDRESS_2 
 # suggestion_info.proximity.address.city_name = INSERT_CITY_NAME 
 # suggestion_info.proximity.radius = INSERT_RADIUS 
 # suggestion_info.proximity.radius_units = RADIUS_UNITS 
 # 
 # For more information on proximities see: 
 # https://developers.google.com/google-ads/api/reference/rpc/latest/ProximityInfo 
 location 
 : 
 LocationInfo 
 = 
 client 
 . 
 get_type 
 ( 
 "LocationInfo" 
 ) 
 # Set the location to the resource name of the given geo target constant. 
 location 
 . 
 geo_target_constant 
 = 
 client 
 . 
 get_service 
 ( 
 "GeoTargetConstantService" 
 ) 
 . 
 geo_target_constant_path 
 ( 
 _GEO_TARGET_CONSTANT 
 ) 
 # Add the LocationInfo object to the list of locations on the 
 # suggestion_info object. You have the option of providing multiple 
 # locations when using location-based suggestions. 
 suggestion_info 
 . 
 location_list 
 . 
 locations 
 . 
 append 
 ( 
 location 
 ) 
 # Set either of the business_profile_location or business_name, depending on 
 # whichever is provided. 
 if 
 business_profile_location 
 : 
 suggestion_info 
 . 
 business_profile_location 
 = 
 business_profile_location 
 else 
 : 
 suggestion_info 
 . 
 business_context 
 . 
 business_name 
 = 
 business_name 
 # Add a schedule detailing which days of the week the business is open. 
 # This schedule describes a schedule in which the business is open on 
 # Mondays from 9am to 5pm. 
 ad_schedule_info 
 : 
 AdScheduleInfo 
 = 
 client 
 . 
 get_type 
 ( 
 "AdScheduleInfo" 
 ) 
 # Set the day of this schedule as Monday. 
 ad_schedule_info 
 . 
 day_of_week 
 = 
 client 
 . 
 enums 
 . 
 DayOfWeekEnum 
 . 
 MONDAY 
 # Set the start hour to 9am. 
 ad_schedule_info 
 . 
 start_hour 
 = 
 9 
 # Set the end hour to 5pm. 
 ad_schedule_info 
 . 
 end_hour 
 = 
 17 
 # Set the start and end minute of zero, for example: 9:00 and 5:00. 
 zero_minute_of_hour 
 : 
 MinuteOfHourEnum 
 . 
 MinuteOfHour 
 = 
 ( 
 client 
 . 
 enums 
 . 
 MinuteOfHourEnum 
 . 
 ZERO 
 ) 
 ad_schedule_info 
 . 
 start_minute 
 = 
 zero_minute_of_hour 
 ad_schedule_info 
 . 
 end_minute 
 = 
 zero_minute_of_hour 
 suggestion_info 
 . 
 ad_schedules 
 . 
 append 
 ( 
 ad_schedule_info 
 ) 
 return 
 suggestion_info 
 def 
  
 get_budget_suggestion 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 suggestion_info 
 : 
 SmartCampaignSuggestionInfo 
 , 
 ) 
 - 
> int 
 : 
  
 """Retrieves a suggested budget amount for a new budget. 
 Using the SmartCampaignSuggestService to determine a daily budget for new 
 and existing Smart campaigns is highly recommended because it helps the 
 campaigns achieve optimal performance. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 suggestion_info: a SmartCampaignSuggestionInfo instance with details 
 about the business being advertised. 
 Returns: 
 a daily budget amount in micros. 
 """ 
 sc_suggest_service 
 : 
 SmartCampaignSuggestServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "SmartCampaignSuggestService" 
 ) 
 request 
 : 
 SuggestSmartCampaignBudgetOptionsRequest 
 = 
 client 
 . 
 get_type 
 ( 
 "SuggestSmartCampaignBudgetOptionsRequest" 
 ) 
 request 
 . 
 customer_id 
 = 
 customer_id 
 # You can retrieve suggestions for an existing campaign by setting the 
 # "campaign" field of the request equal to the resource name of a campaign 
 # and leaving the rest of the request fields below unset: 
 # request.campaign = INSERT_CAMPAIGN_RESOURCE_NAME_HERE 
 # Since these suggestions are for a new campaign, we're going to 
 # use the suggestion_info field instead. 
 request 
 . 
 suggestion_info 
 = 
 suggestion_info 
 # Issue a request to retrieve a budget suggestion. 
 response 
 : 
 SuggestSmartCampaignBudgetOptionsResponse 
 = 
 ( 
 sc_suggest_service 
 . 
 suggest_smart_campaign_budget_options 
 ( 
 request 
 = 
 request 
 ) 
 ) 
 # Three tiers of options will be returned, a "low", "high" and 
 # "recommended". Here we will use the "recommended" option. The amount is 
 # specified in micros, where one million is equivalent to one currency unit. 
 recommendation 
 : 
 SuggestSmartCampaignBudgetOptionsResponse 
 . 
 BudgetOption 
 = 
 ( 
 response 
 . 
 recommended 
 ) 
 print 
 ( 
 f 
 "A daily budget amount of 
 { 
 recommendation 
 . 
 daily_amount_micros 
 } 
 micros " 
 "was suggested, garnering an estimated minimum of " 
 f 
 " 
 { 
 recommendation 
 . 
 metrics 
 . 
 min_daily_clicks 
 } 
 clicks and an estimated " 
 f 
 "maximum of 
 { 
 recommendation 
 . 
 metrics 
 . 
 max_daily_clicks 
 } 
 per day." 
 ) 
 return 
 recommendation 
 . 
 daily_amount_micros 
 def 
  
 get_ad_suggestions 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 suggestion_info 
 : 
 SmartCampaignSuggestionInfo 
 , 
 ) 
 - 
> SmartCampaignAdInfo 
 : 
  
 """Retrieves creative suggestions for a Smart campaign ad. 
 Using the SmartCampaignSuggestService to suggest creatives for new and 
 existing Smart campaigns is highly recommended because it helps the 
 campaigns achieve optimal performance. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 suggestion_info: a SmartCampaignSuggestionInfo instance with details 
 about the business being advertised. 
 Returns: 
 a SmartCampaignAdInfo instance with suggested headlines and 
 descriptions. 
 """ 
 sc_suggest_service 
 : 
 SmartCampaignSuggestServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "SmartCampaignSuggestService" 
 ) 
 request 
 : 
 SuggestSmartCampaignAdRequest 
 = 
 client 
 . 
 get_type 
 ( 
 "SuggestSmartCampaignAdRequest" 
 ) 
 request 
 . 
 customer_id 
 = 
 customer_id 
 # Unlike the SuggestSmartCampaignBudgetOptions method, it's only possible 
 # to use suggestion_info to retrieve ad creative suggestions. 
 request 
 . 
 suggestion_info 
 = 
 suggestion_info 
 # Issue a request to retrieve ad creative suggestions. 
 response 
 : 
 SuggestSmartCampaignAdResponse 
 = 
 ( 
 sc_suggest_service 
 . 
 suggest_smart_campaign_ad 
 ( 
 request 
 = 
 request 
 ) 
 ) 
 # The SmartCampaignAdInfo object in the response contains a list of up to 
 # three headlines and two descriptions. Note that some of the suggestions 
 # may have empty strings as text. Before setting these on the ad you should 
 # review them and filter out any empty values. 
 ad_suggestions 
 : 
 SmartCampaignAdInfo 
 = 
 response 
 . 
 ad_info 
 print 
 ( 
 "The following headlines were suggested:" 
 ) 
 headline 
 : 
 AdTextAsset 
 for 
 headline 
 in 
 ad_suggestions 
 . 
 headlines 
 : 
 print 
 ( 
 f 
 " 
 \t 
 { 
 headline 
 . 
 text 
  
 or 
  
 '<None>' 
 } 
 " 
 ) 
 print 
 ( 
 "And the following descriptions were suggested:" 
 ) 
 description 
 : 
 AdTextAsset 
 for 
 description 
 in 
 ad_suggestions 
 . 
 descriptions 
 : 
 print 
 ( 
 f 
 " 
 \t 
 { 
 description 
 . 
 text 
  
 or 
  
 '<None>' 
 } 
 " 
 ) 
 return 
 ad_suggestions 
 def 
  
 create_campaign_budget_operation 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 suggested_budget_amount 
 : 
 int 
 ) 
 - 
> MutateOperation 
 : 
  
 """Creates a MutateOperation that creates a new CampaignBudget. 
 A temporary ID will be assigned to this campaign budget so that it can be 
 referenced by other objects being created in the same Mutate request. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 suggested_budget_amount: a numeric daily budget amount in micros. 
 Returns: 
 a MutateOperation that creates a CampaignBudget. 
 """ 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 campaign_budget_operation 
 : 
 CampaignBudgetOperation 
 = 
 ( 
 mutate_operation 
 . 
 campaign_budget_operation 
 ) 
 campaign_budget 
 : 
 CampaignBudget 
 = 
 campaign_budget_operation 
 . 
 create 
 campaign_budget 
 . 
 name 
 = 
 f 
 "Smart campaign budget # 
 { 
 uuid4 
 () 
 } 
 " 
 # A budget used for Smart campaigns must have the type SMART_CAMPAIGN. 
 # Note that the field name "type_" is an implementation detail in Python, 
 # the field's actual name is "type". 
 campaign_budget 
 . 
 type_ 
 = 
 client 
 . 
 enums 
 . 
 BudgetTypeEnum 
 . 
 SMART_CAMPAIGN 
 # The suggested budget amount from the SmartCampaignSuggestService is 
 # a daily budget. We don't need to specify that here, because the budget 
 # period already defaults to DAILY. 
 campaign_budget 
 . 
 amount_micros 
 = 
 suggested_budget_amount 
 # Set a temporary ID in the budget's resource name so it can be referenced 
 # by the campaign in later steps. 
 campaign_budget 
 . 
 resource_name 
 = 
 client 
 . 
 get_service 
 ( 
 "CampaignBudgetService" 
 ) 
 . 
 campaign_budget_path 
 ( 
 customer_id 
 , 
 _BUDGET_TEMPORARY_ID 
 ) 
 return 
 mutate_operation 
 def 
  
 create_smart_campaign_operation 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 ) 
 - 
> MutateOperation 
 : 
  
 """Creates a MutateOperation that creates a new Smart campaign. 
 A temporary ID will be assigned to this campaign so that it can 
 be referenced by other objects being created in the same Mutate request. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 Returns: 
 a MutateOperation that creates a campaign. 
 """ 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 campaign_operation 
 : 
 CampaignOperation 
 = 
 mutate_operation 
 . 
 campaign_operation 
 campaign 
 : 
 Campaign 
 = 
 campaign_operation 
 . 
 create 
 campaign 
 . 
 name 
 = 
 f 
 "Smart campaign # 
 { 
 uuid4 
 () 
 } 
 " 
 # Set the campaign status as PAUSED. The campaign is the only entity in 
 # the mutate request that should have its' status set. 
 campaign 
 . 
 status 
 = 
 client 
 . 
 enums 
 . 
 CampaignStatusEnum 
 . 
 PAUSED 
 # Campaign.AdvertisingChannelType is required to be SMART. 
 campaign 
 . 
 advertising_channel_type 
 = 
 ( 
 client 
 . 
 enums 
 . 
 AdvertisingChannelTypeEnum 
 . 
 SMART 
 ) 
 # Campaign.AdvertisingChannelSubType is required to be SMART_CAMPAIGN. 
 campaign 
 . 
 advertising_channel_sub_type 
 = 
 ( 
 client 
 . 
 enums 
 . 
 AdvertisingChannelSubTypeEnum 
 . 
 SMART_CAMPAIGN 
 ) 
 # Assign the resource name with a temporary ID. 
 campaign 
 . 
 resource_name 
 = 
 client 
 . 
 get_service 
 ( 
 "CampaignService" 
 ) 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _SMART_CAMPAIGN_TEMPORARY_ID 
 ) 
 # Set the budget using the given budget resource name. 
 campaign 
 . 
 campaign_budget 
 = 
 client 
 . 
 get_service 
 ( 
 "CampaignBudgetService" 
 ) 
 . 
 campaign_budget_path 
 ( 
 customer_id 
 , 
 _BUDGET_TEMPORARY_ID 
 ) 
 # Declare whether or not this campaign serves political ads targeting the 
 # EU. Valid values are: 
 #   CONTAINS_EU_POLITICAL_ADVERTISING 
 #   DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING 
 campaign 
 . 
 contains_eu_political_advertising 
 = 
 ( 
 client 
 . 
 enums 
 . 
 EuPoliticalAdvertisingStatusEnum 
 . 
 DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING 
 ) 
 return 
 mutate_operation 
 def 
  
 create_smart_campaign_setting_operation 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 business_profile_location 
 : 
 Optional 
 [ 
 str 
 ], 
 business_name 
 : 
 Optional 
 [ 
 str 
 ], 
 ) 
 - 
> MutateOperation 
 : 
  
 """Creates a MutateOperation to create a new SmartCampaignSetting. 
 SmartCampaignSettings are unique in that they only support UPDATE 
 operations, which are used to update and create them. Below we will 
 use a temporary ID in the resource name to associate it with the 
 campaign created in the previous step. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 business_profile_location: the resource name of a Business Profile 
 location. 
 business_name: the name of a Business Profile. 
 Returns: 
 a MutateOperation that creates a SmartCampaignSetting. 
 """ 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 smart_campaign_setting_operation 
 : 
 SmartCampaignSettingOperation 
 = 
 ( 
 mutate_operation 
 . 
 smart_campaign_setting_operation 
 ) 
 smart_campaign_setting 
 : 
 SmartCampaignSetting 
 = 
 ( 
 smart_campaign_setting_operation 
 . 
 update 
 ) 
 # Set a temporary ID in the campaign setting's resource name to associate it 
 # with the campaign created in the previous step. 
 smart_campaign_setting 
 . 
 resource_name 
 = 
 client 
 . 
 get_service 
 ( 
 "SmartCampaignSettingService" 
 ) 
 . 
 smart_campaign_setting_path 
 ( 
 customer_id 
 , 
 _SMART_CAMPAIGN_TEMPORARY_ID 
 ) 
 # Below we configure the SmartCampaignSetting using many of the same 
 # details used to generate a budget suggestion. 
 smart_campaign_setting 
 . 
 phone_number 
 . 
 country_code 
 = 
 _COUNTRY_CODE 
 smart_campaign_setting 
 . 
 phone_number 
 . 
 phone_number 
 = 
 _PHONE_NUMBER 
 smart_campaign_setting 
 . 
 final_url 
 = 
 _LANDING_PAGE_URL 
 smart_campaign_setting 
 . 
 advertising_language_code 
 = 
 _LANGUAGE_CODE 
 # Set either of the business_profile_location or business_name, depending on 
 # whichever is provided. 
 if 
 business_profile_location 
 : 
 smart_campaign_setting 
 . 
 business_profile_location 
 = 
 ( 
 business_profile_location 
 ) 
 else 
 : 
 smart_campaign_setting 
 . 
 business_name 
 = 
 business_name 
 # Set the update mask on the operation. This is required since the smart 
 # campaign setting is created in an UPDATE operation. Here the update 
 # mask will be a list of all the fields that were set on the 
 # SmartCampaignSetting. 
 client 
 . 
 copy_from 
 ( 
 smart_campaign_setting_operation 
 . 
 update_mask 
 , 
 protobuf_helpers 
 . 
 field_mask 
 ( 
 None 
 , 
 smart_campaign_setting 
 . 
 _pb 
 ), 
 ) 
 return 
 mutate_operation 
 def 
  
 create_campaign_criterion_operations 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 keyword_theme_infos 
 : 
 List 
 [ 
 KeywordThemeInfo 
 ], 
 suggestion_info 
 : 
 SmartCampaignSuggestionInfo 
 , 
 ) 
 - 
> List 
 [ 
 MutateOperation 
 ]: 
  
 """Creates a list of MutateOperations that create new campaign criteria. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 keyword_theme_infos: a list of KeywordThemeInfos. 
 suggestion_info: A SmartCampaignSuggestionInfo instance. 
 Returns: 
 a list of MutateOperations that create new campaign criteria. 
 """ 
 campaign_service 
 : 
 CampaignServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "CampaignService" 
 ) 
 operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 [] 
 info 
 : 
 KeywordThemeInfo 
 for 
 info 
 in 
 keyword_theme_infos 
 : 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 campaign_criterion_operation 
 : 
 CampaignCriterionOperation 
 = 
 ( 
 mutate_operation 
 . 
 campaign_criterion_operation 
 ) 
 campaign_criterion 
 : 
 CampaignCriterion 
 = 
 ( 
 campaign_criterion_operation 
 . 
 create 
 ) 
 # Set the campaign ID to a temporary ID. 
 campaign_criterion 
 . 
 campaign 
 = 
 campaign_service 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _SMART_CAMPAIGN_TEMPORARY_ID 
 ) 
 # Set the keyword theme to the given KeywordThemeInfo. 
 campaign_criterion 
 . 
 keyword_theme 
 . 
 CopyFrom 
 ( 
 info 
 ) 
 # Add the mutate operation to the list of other operations. 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 # Create a location criterion for each location in the suggestion info 
 # object to add corresponding location targeting to the Smart campaign 
 location_info 
 : 
 LocationInfo 
 for 
 location_info 
 in 
 suggestion_info 
 . 
 location_list 
 . 
 locations 
 : 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 campaign_criterion_operation 
 : 
 CampaignCriterionOperation 
 = 
 ( 
 mutate_operation 
 . 
 campaign_criterion_operation 
 ) 
 campaign_criterion 
 : 
 CampaignCriterion 
 = 
 ( 
 campaign_criterion_operation 
 . 
 create 
 ) 
 # Set the campaign ID to a temporary ID. 
 campaign_criterion 
 . 
 campaign 
 = 
 campaign_service 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _SMART_CAMPAIGN_TEMPORARY_ID 
 ) 
 # Set the location to the given location. 
 campaign_criterion 
 . 
 location 
 . 
 CopyFrom 
 ( 
 location_info 
 ) 
 # Add the mutate operation to the list of other operations. 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 return 
 operations 
 def 
  
 create_ad_group_operation 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 ) 
 - 
> MutateOperation 
 : 
  
 """Creates a MutateOperation that creates a new ad group. 
 A temporary ID will be used in the campaign resource name for this 
 ad group to associate it with the Smart campaign created in earlier steps. 
 A temporary ID will also be used for its own resource name so that we can 
 associate an ad group ad with it later in the process. 
 Only one ad group can be created for a given Smart campaign. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 Returns: 
 a MutateOperation that creates a new ad group. 
 """ 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 ad_group_operation 
 : 
 AdGroupOperation 
 = 
 mutate_operation 
 . 
 ad_group_operation 
 ad_group 
 : 
 AdGroup 
 = 
 ad_group_operation 
 . 
 create 
 # Set the ad group ID to a temporary ID. 
 ad_group 
 . 
 resource_name 
 = 
 client 
 . 
 get_service 
 ( 
 "AdGroupService" 
 ) 
 . 
 ad_group_path 
 ( 
 customer_id 
 , 
 _AD_GROUP_TEMPORARY_ID 
 ) 
 ad_group 
 . 
 name 
 = 
 f 
 "Smart campaign ad group # 
 { 
 uuid4 
 () 
 } 
 " 
 # Set the campaign ID to a temporary ID. 
 ad_group 
 . 
 campaign 
 = 
 client 
 . 
 get_service 
 ( 
 "CampaignService" 
 ) 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _BUDGET_TEMPORARY_ID 
 ) 
 # The ad group type must be set to SMART_CAMPAIGN_ADS. 
 ad_group 
 . 
 type_ 
 = 
 client 
 . 
 enums 
 . 
 AdGroupTypeEnum 
 . 
 SMART_CAMPAIGN_ADS 
 return 
 mutate_operation 
 def 
  
 create_ad_group_ad_operation 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 ad_suggestions 
 : 
 SmartCampaignAdInfo 
 , 
 ) 
 - 
> MutateOperation 
 : 
  
 """Creates a MutateOperation that creates a new ad group ad. 
 A temporary ID will be used in the ad group resource name for this 
 ad group ad to associate it with the ad group created in earlier steps. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 ad_suggestions: a SmartCampaignAdInfo object with ad creative 
 suggestions. 
 Returns: 
 a MutateOperation that creates a new ad group ad. 
 """ 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 ad_group_ad_operation 
 : 
 AdGroupAdOperation 
 = 
 ( 
 mutate_operation 
 . 
 ad_group_ad_operation 
 ) 
 ad_group_ad 
 : 
 AdGroupAd 
 = 
 ad_group_ad_operation 
 . 
 create 
 # Set the ad group ID to a temporary ID. 
 ad_group_ad 
 . 
 ad_group 
 = 
 client 
 . 
 get_service 
 ( 
 "AdGroupService" 
 ) 
 . 
 ad_group_path 
 ( 
 customer_id 
 , 
 _AD_GROUP_TEMPORARY_ID 
 ) 
 # Set the type to SMART_CAMPAIGN_AD. 
 ad_group_ad 
 . 
 ad 
 . 
 type_ 
 = 
 client 
 . 
 enums 
 . 
 AdTypeEnum 
 . 
 SMART_CAMPAIGN_AD 
 ad 
 : 
 SmartCampaignAdInfo 
 = 
 ad_group_ad 
 . 
 ad 
 . 
 smart_campaign_ad 
 # The SmartCampaignAdInfo object includes headlines and descriptions 
 # retrieved from the SmartCampaignSuggestService.SuggestSmartCampaignAd 
 # method. It's recommended that users review and approve or update these 
 # creatives before they're set on the ad. It's possible that some or all of 
 # these assets may contain empty texts, which should not be set on the ad 
 # and instead should be replaced with meaningful texts from the user. Below 
 # we just accept the creatives that were suggested while filtering out empty 
 # assets. If no headlines or descriptions were suggested, then we manually 
 # add some, otherwise this operation will generate an INVALID_ARGUMENT 
 # error. Individual workflows will likely vary here. 
 ad 
 . 
 headlines 
 . 
 extend 
 ( 
 [ 
 asset 
 for 
 asset 
 in 
 ad_suggestions 
 . 
 headlines 
 if 
 asset 
 . 
 text 
 ] 
 ) 
 num_missing_headlines 
 : 
 int 
 = 
 _REQUIRED_NUM_HEADLINES 
 - 
 len 
 ( 
 ad 
 . 
 headlines 
 ) 
 # If there are fewer headlines than are required, we manually add additional 
 # headlines to make up for the difference. 
 for 
 i 
 in 
 range 
 ( 
 num_missing_headlines 
 ): 
 headline 
 : 
 AdTextAsset 
 = 
 client 
 . 
 get_type 
 ( 
 "AdTextAsset" 
 ) 
 headline 
 . 
 text 
 = 
 f 
 "placeholder headline 
 { 
 i 
 } 
 " 
 ad 
 . 
 headlines 
 . 
 append 
 ( 
 headline 
 ) 
 ad 
 . 
 descriptions 
 . 
 extend 
 ( 
 asset 
 for 
 asset 
 in 
 ad_suggestions 
 . 
 descriptions 
 if 
 asset 
 . 
 text 
 ) 
 num_missing_descriptions 
 : 
 int 
 = 
 _REQUIRED_NUM_DESCRIPTIONS 
 - 
 len 
 ( 
 ad 
 . 
 descriptions 
 ) 
 # If there are fewer descriptions than are required, we manually add 
 # additional descriptions to make up for the difference. 
 for 
 i 
 in 
 range 
 ( 
 num_missing_descriptions 
 ): 
 description 
 : 
 AdTextAsset 
 = 
 client 
 . 
 get_type 
 ( 
 "AdTextAsset" 
 ) 
 description 
 . 
 text 
 = 
 f 
 "placeholder description 
 { 
 i 
 } 
 " 
 ad 
 . 
 descriptions 
 . 
 append 
 ( 
 description 
 ) 
 return 
 mutate_operation 
 def 
  
 print_response_details 
 ( 
 response 
 : 
 MutateGoogleAdsResponse 
 ) 
 - 
> None 
 : 
  
 """Prints the details of a MutateGoogleAdsResponse. 
 Parses the "response" oneof field name and uses it to extract the new 
 entity's name and resource name. 
 Args: 
 response: a MutateGoogleAdsResponse object. 
 """ 
 # Parse the Mutate response to print details about the entities that 
 # were created by the request. 
 result 
 : 
 MutateOperationResponse 
 for 
 result 
 in 
 response 
 . 
 mutate_operation_responses 
 : 
 resource_type 
 : 
 str 
 = 
 "unrecognized" 
 resource_name 
 : 
 str 
 = 
 "not found" 
 if 
 result 
 . 
 _pb 
 . 
 HasField 
 ( 
 "campaign_budget_result" 
 ): 
 resource_type 
 = 
 "CampaignBudget" 
 resource_name 
 = 
 result 
 . 
 campaign_budget_result 
 . 
 resource_name 
 elif 
 result 
 . 
 _pb 
 . 
 HasField 
 ( 
 "campaign_result" 
 ): 
 resource_type 
 = 
 "Campaign" 
 resource_name 
 = 
 result 
 . 
 campaign_result 
 . 
 resource_name 
 elif 
 result 
 . 
 _pb 
 . 
 HasField 
 ( 
 "smart_campaign_setting_result" 
 ): 
 resource_type 
 = 
 "SmartCampaignSettingResult" 
 resource_name 
 = 
 result 
 . 
 smart_campaign_setting_result 
 . 
 resource_name 
 elif 
 result 
 . 
 _pb 
 . 
 HasField 
 ( 
 "campaign_criterion_result" 
 ): 
 resource_type 
 = 
 "CampaignCriterion" 
 resource_name 
 = 
 result 
 . 
 campaign_criterion_result 
 . 
 resource_name 
 elif 
 result 
 . 
 _pb 
 . 
 HasField 
 ( 
 "ad_group_result" 
 ): 
 resource_type 
 = 
 "AdGroup" 
 resource_name 
 = 
 result 
 . 
 ad_group_result 
 . 
 resource_name 
 elif 
 result 
 . 
 _pb 
 . 
 HasField 
 ( 
 "ad_group_ad_result" 
 ): 
 resource_type 
 = 
 "AdGroupAd" 
 resource_name 
 = 
 result 
 . 
 ad_group_ad_result 
 . 
 resource_name 
 print 
 ( 
 f 
 "Created a(n) 
 { 
 resource_type 
 } 
 with " 
 f 
 "resource_name: ' 
 { 
 resource_name 
 } 
 '." 
 ) 
 if 
 __name__ 
 == 
 "__main__" 
 : 
 parser 
 : 
 argparse 
 . 
 ArgumentParser 
 = 
 argparse 
 . 
 ArgumentParser 
 ( 
 description 
 = 
 ( 
 "Creates a Smart campaign." 
 ) 
 ) 
 # 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." 
 , 
 ) 
 parser 
 . 
 add_argument 
 ( 
 "-k" 
 , 
 "--keyword_text" 
 , 
 type 
 = 
 str 
 , 
 required 
 = 
 False 
 , 
 help 
 = 
 ( 
 "A keyword text used to retrieve keyword theme constant " 
 "suggestions from the KeywordThemeConstantService. These keyword " 
 "theme suggestions are generated using auto-completion data for " 
 "the given text and may help improve the performance of " 
 "the Smart campaign." 
 ), 
 ) 
 parser 
 . 
 add_argument 
 ( 
 "-f" 
 , 
 "--free_form_keyword_text" 
 , 
 type 
 = 
 str 
 , 
 required 
 = 
 False 
 , 
 help 
 = 
 ( 
 "A keyword text used to create a freeform keyword theme, which is " 
 "entirely user-specified and not derived from any suggestion " 
 "service. Using free-form keyword themes is typically not " 
 "recommended because they are less effective than suggested " 
 "keyword themes, however they are useful in situations where a " 
 "very specific term needs to be targeted." 
 ), 
 ) 
 group 
 : 
 argparse 
 . 
 _MutuallyExclusiveGroup 
 = 
 ( 
 parser 
 . 
 add_mutually_exclusive_group 
 ( 
 required 
 = 
 True 
 ) 
 ) 
 group 
 . 
 add_argument 
 ( 
 "-b" 
 , 
 "--business_profile_location" 
 , 
 type 
 = 
 str 
 , 
 help 
 = 
 ( 
 "Optional: Specify the resource name of a Business Profile location. This" 
 "is required if a business name is not provided. It can be retrieved" 
 "using the Business Profile API, see:" 
 "https://developers.google.com/my-business/reference/businessinformation/rest/v1/accounts.locations" 
 "or from the Business Profile UI (https://support.google.com/business/answer/10737668)." 
 ), 
 ) 
 group 
 . 
 add_argument 
 ( 
 "-n" 
 , 
 "--business_name" 
 , 
 type 
 = 
 str 
 , 
 help 
 = 
 ( 
 "The name of a Business Profile business. This is required " 
 "if a business profile location is not provided." 
 ), 
 ) 
 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 
 . 
 keyword_text 
 , 
 args 
 . 
 free_form_keyword_text 
 , 
 args 
 . 
 business_profile_location 
 , 
 args 
 . 
 business_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

 #!/usr/bin/env ruby 
 # Encoding: utf-8 
 # 
 # Copyright 2021 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 Smart campaign. 
 # More details on Smart campaigns can be found here: 
 # https://support.google.com/google-ads/answer/7652860 
 require 
  
 'optparse' 
 require 
  
 'date' 
 require 
  
 'open-uri' 
 require 
  
 'google/ads/google_ads' 
 def 
  
 add_smart_campaign 
 ( 
  
 customer_id 
 , 
  
 keyword_text 
 , 
  
 free_form_keyword_text 
 , 
  
 business_profile_location 
 , 
  
 business_name 
 ) 
  
 # GoogleAdsClient will read a config file from 
  
 # ENV['HOME']/google_ads_config.rb when called without parameters 
  
 client 
  
 = 
  
 Google 
 :: 
 Ads 
 :: 
 GoogleAds 
 :: 
 GoogleAdsClient 
 . 
 new 
  
 # The SmartCampaignSuggestionInfo object acts as the basis for many of the 
  
 # entities necessary to create a Smart campaign. It will be reused a number 
  
 # of times to retrieve suggestions for keyword themes, budget amount, 
  
 # ad creatives, and campaign criteria. 
  
 suggestion_info 
  
 = 
  
 get_smart_campaign_suggestion_info 
 ( 
  
 client 
 , 
  
 business_profile_location 
 , 
  
 business_name 
 , 
  
 ) 
  
 # After creating a SmartCampaignSuggestionInfo object we first use it to 
  
 # generate a list of keyword themes using the SuggestKeywordThemes method 
  
 # on the SmartCampaignSuggestService. It is strongly recommended that you 
  
 # use this strategy for generating keyword themes. 
  
 keyword_themes 
  
 = 
  
 get_keyword_theme_suggestions 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 suggestion_info 
 , 
  
 ) 
  
 # If a keyword text is given, retrieve keyword theme constant suggestions 
  
 # from the KeywordThemeConstantService, map them to KeywordThemes, and append 
  
 # them to the existing list. This logic should ideally only be used if the 
  
 # suggestions from the get_keyword_theme_suggestions function are 
  
 # insufficient. 
  
 if 
  
 keyword_text 
  
 keyword_themes 
  
 += 
  
 get_keyword_text_auto_completions 
 ( 
  
 client 
 , 
  
 keyword_text 
 , 
  
 ) 
  
 end 
  
 # Map the KeywordThemeConstants retrieved by the previous two steps to 
  
 # KeywordThemeInfo instances. 
  
 keyword_theme_infos 
  
 = 
  
 map_keyword_themes_to_keyword_infos 
 ( 
  
 client 
 , 
  
 keyword_themes 
 , 
  
 ) 
  
 # If a free-form keyword text is given we create a KeywordThemeInfo instance 
  
 # from it and add it to the existing list. 
  
 if 
  
 free_form_keyword_text 
  
 keyword_theme_infos 
 << 
 get_freeform_keyword_theme_info 
 ( 
  
 client 
 , 
  
 free_form_keyword_text 
 , 
  
 ) 
  
 end 
  
 # Now add the generated keyword themes to the suggestion info instance. 
  
 suggestion_info 
 . 
 keyword_themes 
  
 += 
  
 keyword_theme_infos 
  
 suggested_budget_amount 
  
 = 
  
 get_budget_suggestion 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 suggestion_info 
 , 
  
 ) 
  
 ad_suggestions 
  
 = 
  
 get_ad_suggestions 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 suggestion_info 
 , 
  
 ) 
  
 # The below methods create and return MutateOperations that we later 
  
 # provide to the GoogleAdsService.Mutate method in order to create the 
  
 # entities in a single request. Since the entities for a Smart campaign 
  
 # are closely tied to one-another it's considered a best practice to 
  
 # create them in a single Mutate request so they all complete successfully 
  
 # or fail entirely, leaving no orphaned entities. See: 
  
 # https://developers.google.com/google-ads/api/docs/mutating/overview 
  
 mutate_operations 
  
 = 
  
 [] 
  
 # It's important to create these operations in this order because 
  
 # they depend on each other, for example the SmartCampaignSetting 
  
 # and ad group depend on the campaign, and the ad group ad depends 
  
 # on the ad group. 
  
 mutate_operations 
 << 
 create_campaign_budget_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 suggested_budget_amount 
 , 
  
 ) 
  
 mutate_operations 
 << 
 create_smart_campaign_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 ) 
  
 mutate_operations 
 << 
 create_smart_campaign_setting_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 business_profile_location 
 , 
  
 business_name 
 , 
  
 ) 
  
 mutate_operations 
  
 += 
  
 create_campaign_criterion_operations 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 keyword_theme_infos 
 , 
  
 suggestion_info 
 , 
  
 ) 
  
 mutate_operations 
 << 
 create_ad_group_operation 
 ( 
 client 
 , 
  
 customer_id 
 ) 
  
 mutate_operations 
 << 
 create_ad_group_ad_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 ad_suggestions 
  
 ) 
  
 # Sends the operations into a single Mutate request. 
  
 response 
  
 = 
  
 client 
 . 
 service 
 . 
 google_ads 
 . 
 mutate 
 ( 
  
 customer_id 
 : 
  
 customer_id 
 , 
  
 mutate_operations 
 : 
  
 mutate_operations 
 , 
  
 ) 
  
 print_response_details 
 ( 
 response 
 ) 
 end 
 def 
  
 get_keyword_theme_suggestions 
 ( 
 client 
 , 
  
 customer_id 
 , 
  
 suggestion_info 
 ) 
  
 response 
  
 = 
  
 client 
 . 
 service 
 . 
 smart_campaign_suggest 
 . 
 suggest_keyword_themes 
 ( 
  
 customer_id 
 : 
  
 customer_id 
 , 
  
 suggestion_info 
 : 
  
 suggestion_info 
 , 
  
 ) 
  
 puts 
  
 "Retrieved 
 #{ 
 response 
 . 
 keyword_themes 
 . 
 size 
 } 
 keyword theme" 
  
 \ 
  
 " suggestions from SuggestKeywordThemes service." 
  
 return 
  
 response 
 . 
 keyword_themes 
 end 
 # Retrieves keyword_theme_constants for the given criteria. 
 # These KeywordThemeConstants are derived from autocomplete data for the given 
 # keyword text. They are mapped to KeywordThemes before being returned. 
 def 
  
 get_keyword_text_auto_completions 
 ( 
 client 
 , 
  
 keyword_text 
 ) 
  
 response 
  
 = 
  
 client 
 . 
 service 
 . 
 keyword_theme_constant 
 . 
 suggest_keyword_theme_constants 
 ( 
  
 query_text 
 : 
  
 keyword_text 
 , 
  
 country_code 
 : 
  
 COUNTRY_CODE 
 , 
  
 language_code 
 : 
  
 LANGUAGE_CODE 
 , 
  
 ) 
  
 puts 
  
 "Retrieved 
 #{ 
 response 
 . 
 keyword_theme_constants 
 . 
 size 
 } 
 keyword theme" 
  
 \ 
  
 "constants using the keyword: ' 
 #{ 
 keyword_text 
 } 
 '" 
  
 response 
 . 
 keyword_theme_constants 
 . 
 map 
  
 do 
  
 | 
 ktc 
 | 
  
 client 
 . 
 resource 
 . 
 keyword_theme 
  
 do 
  
 | 
 kt 
 | 
  
 kt 
 . 
 keyword_theme_constant 
  
 = 
  
 ktc 
  
 end 
  
 end 
 end 
 def 
  
 get_freeform_keyword_theme_info 
 ( 
 client 
 , 
  
 free_form_keyword_text 
 ) 
  
 client 
 . 
 resource 
 . 
 keyword_theme_info 
  
 do 
  
 | 
 kti 
 | 
  
 kti 
 . 
 free_form_keyword_theme 
  
 = 
  
 free_form_keyword_text 
  
 end 
 end 
 # Maps a list of keyword_theme_constants to keyword_theme_infos. 
 def 
  
 map_keyword_themes_to_keyword_infos 
 ( 
 client 
 , 
  
 keyword_themes 
 ) 
  
 keyword_themes 
 . 
 map 
  
 do 
  
 | 
 kt 
 | 
  
 client 
 . 
 resource 
 . 
 keyword_theme_info 
  
 do 
  
 | 
 kti 
 | 
  
 if 
  
 kt 
 . 
 keyword_theme_constant 
  
 kti 
 . 
 keyword_theme_constant 
  
 = 
  
 kt 
 . 
 keyword_theme_constant 
 . 
 resource_name 
  
 elsif 
  
 kt 
 . 
 free_form_keyword_theme 
  
 kti 
 . 
 free_form_keyword_theme 
  
 = 
  
 kt 
 . 
 free_form_keyword_theme 
  
 else 
  
 raise 
  
 "Malformed keyword_theme 
 #{ 
 kt 
 } 
 " 
  
 end 
  
 end 
  
 end 
 end 
 # Builds a SmartCampaignSuggestionInfo object with business details. 
 # 
 # The details are used by the SmartCampaignSuggestService to suggest a 
 # budget amount as well as creatives for the ad. 
 # 
 # Note that when retrieving ad creative suggestions it's required that the 
 # "final_url", "language_code" and "keyword_themes" fields are set on the 
 # SmartCampaignSuggestionInfo instance. 
 def 
  
 get_smart_campaign_suggestion_info 
 ( 
  
 client 
 , 
  
 business_profile_location 
 , 
  
 business_name 
 ) 
  
 # Since these suggestions are for a new campaign, we're going to 
  
 # use the suggestion_info field instead. 
  
 suggestion_info 
  
 = 
  
 client 
 . 
 resource 
 . 
 smart_campaign_suggestion_info 
  
 do 
  
 | 
 si 
 | 
  
 # Adds the URL of the campaign's landing page. 
  
 si 
 . 
 final_url 
  
 = 
  
 LANDING_PAGE_URL 
  
 # Add the language code for the campaign. 
  
 si 
 . 
 language_code 
  
 = 
  
 LANGUAGE_CODE 
  
 # Constructs location information using the given geo target constant. It's 
  
 # also possible to provide a geographic proximity using the "proximity" 
  
 # field on suggestion_info, for example: 
  
 # si.proximity = client.resource.proximity_info do |proximity| 
  
 #   proximity.address = client.resource.address_info do |address| 
  
 #     address.post_code = INSERT_POSTAL_CODE 
  
 #     address.province_code = INSERT_PROVINCE_CODE 
  
 #     address.country_code = INSERT_COUNTRY_CODE 
  
 #     address.province_name = INSERT_PROVINCE_NAME 
  
 #     address.street_address = INSERT_STREET_ADDRESS 
  
 #     address.street_address2 = INSERT_STREET_ADDRESS_2 
  
 #     address.city_name = INSERT_CITY_NAME 
  
 #   end 
  
 #   proximity.radius = INSERT_RADIUS 
  
 #   proximity.radius_units = :INSERT_RADIUS_UNIT_ENUM 
  
 # end 
  
 # 
  
 # For more information on proximities see: 
  
 # https://developers.google.com/google-ads/api/reference/rpc/latest/ProximityInfo 
  
 si 
 . 
 location_list 
  
 = 
  
 client 
 . 
 resource 
 . 
 location_list 
  
 do 
  
 | 
 loc_list 
 | 
  
 # Adds the location_info object to the list of locations on the 
  
 # suggestion_info object. You have the option of providing multiple 
  
 # locations when using location-based suggestions. 
  
 loc_list 
 . 
 locations 
 << 
 client 
 . 
 resource 
 . 
 location_info 
  
 do 
  
 | 
 li 
 | 
  
 li 
 . 
 geo_target_constant 
  
 = 
  
 client 
 . 
 path 
 . 
 geo_target_constant 
 ( 
 GEO_TARGET_CONSTANT 
 ) 
  
 end 
  
 end 
  
 # Set either of the business_profile_location or business_name, depending on 
  
 # whichever is provided. 
  
 if 
  
 business_profile_location 
  
 si 
 . 
 business_profile_location 
  
 = 
  
 business_profile_location 
  
 else 
  
 si 
 . 
 business_context 
  
 = 
  
 client 
 . 
 resource 
 . 
 business_context 
  
 do 
  
 | 
 bc 
 | 
  
 bc 
 . 
 business_name 
  
 = 
  
 business_name 
  
 end 
  
 end 
  
 # Adds a schedule detailing which days of the week the business is open. 
  
 # This schedule describes a schedule in which the business is open on 
  
 # Mondays from 9am to 5pm. 
  
 si 
 . 
 ad_schedules 
  
 += 
  
 [ 
  
 client 
 . 
 resource 
 . 
 ad_schedule_info 
  
 do 
  
 | 
 as 
 | 
  
 # Sets the day of this schedule as Monday. 
  
 as 
 . 
 day_of_week 
  
 = 
  
 :MONDAY 
  
 # Sets the start hour to 9:00am. 
  
 as 
 . 
 start_hour 
  
 = 
  
 9 
  
 as 
 . 
 start_minute 
  
 = 
  
 :ZERO 
  
 # Sets the end hour to 5:00pm. 
  
 as 
 . 
 end_hour 
  
 = 
  
 17 
  
 as 
 . 
 end_minute 
  
 = 
  
 :ZERO 
  
 end 
  
 ] 
  
 end 
  
 suggestion_info 
 end 
 # Retrieves a suggested budget amount for a new budget. 
 # 
 # Using the SmartCampaignSuggestService to determine a daily budget for new 
 # and existing Smart campaigns is highly recommended because it helps the 
 # campaigns achieve optimal performance. 
 def 
  
 get_budget_suggestion 
 ( 
 client 
 , 
  
 customer_id 
 , 
  
 suggestion_info 
 ) 
  
 # Issues a request to retrieve a budget suggestion. 
  
 response 
  
 = 
  
 client 
 . 
 service 
 . 
 smart_campaign_suggest 
 . 
 suggest_smart_campaign_budget_options 
 ( 
  
 customer_id 
 : 
  
 customer_id 
 , 
  
 # You can retrieve suggestions for an existing campaign by setting the 
  
 # "campaign" field of the request equal to the resource name of a campaign 
  
 # and leaving the rest of the request fields below unset: 
  
 # campaign: INSERT_CAMPAIGN_RESOURCE_NAME_HERE, 
  
 # Since these suggestions are for a new campaign, we're going to 
  
 # use the suggestion_info field instead. 
  
 suggestion_info 
 : 
  
 suggestion_info 
 , 
  
 ) 
  
 # Three tiers of options will be returned, a "low", "high" and 
  
 # "recommended". Here we will use the "recommended" option. The amount is 
  
 # specified in micros, where one million is equivalent to one currency unit. 
  
 recommendation 
  
 = 
  
 response 
 . 
 recommended 
  
 puts 
  
 "A daily budget amount of 
 #{ 
 recommendation 
 . 
 daily_amount_micros 
 } 
 micros" 
  
 \ 
  
 " was suggested, garnering an estimated minimum of" 
  
 \ 
  
 " 
 #{ 
 recommendation 
 . 
 metrics 
 . 
 min_daily_clicks 
 } 
 clicks and an estimated" 
  
 \ 
  
 " maximum of 
 #{ 
 recommendation 
 . 
 metrics 
 . 
 max_daily_clicks 
 } 
 per day." 
  
 recommendation 
 . 
 daily_amount_micros 
 end 
 # Retrieves creative suggestions for a Smart campaign ad. 
 # 
 # Using the SmartCampaignSuggestService to suggest creatives for new and 
 # existing Smart campaigns is highly recommended because it helps the 
 # campaigns achieve optimal performance. 
 def 
  
 get_ad_suggestions 
 ( 
 client 
 , 
  
 customer_id 
 , 
  
 suggestion_info 
 ) 
  
 # Issue a request to retrieve ad creative suggestions. 
  
 response 
  
 = 
  
 client 
 . 
 service 
 . 
 smart_campaign_suggest 
 . 
 suggest_smart_campaign_ad 
 ( 
  
 customer_id 
 : 
  
 customer_id 
 , 
  
 # Unlike the SuggestSmartCampaignBudgetOptions method, it's only possible 
  
 # to use suggestion_info to retrieve ad creative suggestions. 
  
 suggestion_info 
 : 
  
 suggestion_info 
 , 
  
 ) 
  
 # The SmartCampaignAdInfo object in the response contains a list of up to 
  
 # three headlines and two descriptions. Note that some of the suggestions 
  
 # may have empty strings as text. Before setting these on the ad you should 
  
 # review them and filter out any empty values. 
  
 ad_suggestions 
  
 = 
  
 response 
 . 
 ad_info 
  
 # If there are no suggestions, the response will be blank. 
  
 return 
  
 nil 
  
 if 
  
 ad_suggestions 
 . 
 nil? 
  
 puts 
  
 'The following headlines were suggested:' 
  
 ad_suggestions 
 . 
 headlines 
 . 
 each 
  
 do 
  
 | 
 headline 
 | 
  
 puts 
  
 " 
 \t 
 #{ 
 headline 
 . 
 text 
  
 || 
  
 '<None>' 
 } 
 " 
  
 end 
  
 puts 
  
 'And the following descriptions were suggested:' 
  
 ad_suggestions 
 . 
 descriptions 
 . 
 each 
  
 do 
  
 | 
 description 
 | 
  
 puts 
  
 " 
 \t 
 #{ 
 description 
 . 
 text 
  
 || 
  
 '<None>' 
 } 
 " 
  
 end 
  
 ad_suggestions 
 end 
 # Creates a mutate_operation that creates a new campaign_budget. 
 # A temporary ID will be assigned to this campaign budget so that it can be 
 # referenced by other objects being created in the same mutate request. 
 def 
  
 create_campaign_budget_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 suggested_budget_amount 
 ) 
  
 mutate_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_budget_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 campaign_budget 
  
 do 
  
 | 
 cb 
 | 
  
 cb 
 . 
 name 
  
 = 
  
 "Smart campaign budget # 
 #{ 
 ( 
 Time 
 . 
 new 
 . 
 to_f 
  
 * 
  
 1000 
 ) 
 . 
 to_i 
 } 
 " 
  
 # A budget used for Smart campaigns must have the type SMART_CAMPAIGN. 
  
 cb 
 . 
 type 
  
 = 
  
 :SMART_CAMPAIGN 
  
 # The suggested budget amount from the smart_campaign_suggest_service is 
  
 # a daily budget. We don't need to specify that here, because the budget 
  
 # period already defaults to DAILY. 
  
 cb 
 . 
 amount_micros 
  
 = 
  
 suggested_budget_amount 
  
 # Sets a temporary ID in the budget's resource name so it can be referenced 
  
 # by the campaign in later steps. 
  
 cb 
 . 
 resource_name 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign_budget 
 ( 
 customer_id 
 , 
  
 BUDGET_TEMPORARY_ID 
 ) 
  
 end 
  
 end 
  
 mutate_operation 
 end 
 # Creates a mutate_operation that creates a new Smart campaign. 
 # A temporary ID will be assigned to this campaign so that it can 
 # be referenced by other objects being created in the same mutate request. 
 def 
  
 create_smart_campaign_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 ) 
  
 mutate_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 campaign 
  
 do 
  
 | 
 c 
 | 
  
 c 
 . 
 name 
  
 = 
  
 "Smart campaign # 
 #{ 
 ( 
 Time 
 . 
 new 
 . 
 to_f 
  
 * 
  
 1000 
 ) 
 . 
 to_i 
 } 
 " 
  
 # Sets the campaign status as PAUSED. The campaign is the only entity in 
  
 # the mutate request that should have its' status set. 
  
 c 
 . 
 status 
  
 = 
  
 :PAUSED 
  
 # campaign.advertising_channel_type is required to be SMART. 
  
 c 
 . 
 advertising_channel_type 
  
 = 
  
 :SMART 
  
 # campaign.advertising_channel_sub_type is required to be SMART_CAMPAIGN. 
  
 c 
 . 
 advertising_channel_sub_type 
  
 = 
  
 :SMART_CAMPAIGN 
  
 # Assigns the resource name with a temporary ID. 
  
 c 
 . 
 resource_name 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
 customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 c 
 . 
 campaign_budget 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign_budget 
 ( 
 customer_id 
 , 
  
 BUDGET_TEMPORARY_ID 
 ) 
  
 # Declare whether or not this campaign serves political ads targeting the EU. 
  
 # Valid values are CONTAINS_EU_POLITICAL_ADVERTISING and 
  
 # DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING. 
  
 c 
 . 
 contains_eu_political_advertising 
  
 = 
  
 :DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING 
  
 end 
  
 end 
  
 mutate_operation 
 end 
 # Creates a mutate_operation to create a new smart_campaign_setting. 
 # smart_campaign_settings are unique in that they only support UPDATE 
 # operations, which are used to update and create them. Below we will 
 # use a temporary ID in the resource name to associate it with the 
 # campaign created in the previous step. 
 def 
  
 create_smart_campaign_setting_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 business_profile_location 
 , 
  
 business_name 
 ) 
  
 mutate_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 smart_campaign_setting_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 update_resource 
 . 
 smart_campaign_setting 
 ( 
  
 # Sets a temporary ID in the campaign setting's resource name to 
  
 # associate it with the campaign created in the previous step. 
  
 client 
 . 
 path 
 . 
 smart_campaign_setting 
 ( 
  
 customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 ) 
  
 do 
  
 | 
 scs 
 | 
  
 # Below we configure the smart_campaign_setting using many of the same 
  
 # details used to generate a budget suggestion. 
  
 scs 
 . 
 phone_number 
  
 = 
  
 client 
 . 
 resource 
 . 
 phone_number 
  
 do 
  
 | 
 p 
 | 
  
 p 
 . 
 country_code 
  
 = 
  
 COUNTRY_CODE 
  
 p 
 . 
 phone_number 
  
 = 
  
 PHONE_NUMBER 
  
 end 
  
 scs 
 . 
 final_url 
  
 = 
  
 LANDING_PAGE_URL 
  
 scs 
 . 
 advertising_language_code 
  
 = 
  
 LANGUAGE_CODE 
  
 # It's required that either a business location ID or a business name is 
  
 # added to the smart_campaign_setting. 
  
 if 
  
 business_profile_location 
  
 scs 
 . 
 business_profile_location 
  
 = 
  
 business_profile_location 
  
 else 
  
 scs 
 . 
 business_name 
  
 = 
  
 business_name 
  
 end 
  
 end 
  
 end 
  
 mutate_operation 
 end 
 # Creates a list of mutate_operations that create new campaign criteria. 
 def 
  
 create_campaign_criterion_operations 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 keyword_theme_infos 
 , 
  
 suggestion_info 
 ) 
  
 operations 
  
 = 
  
 [] 
  
 keyword_theme_infos 
 . 
 each 
  
 do 
  
 | 
 info 
 | 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_criterion_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 campaign_criterion 
  
 do 
  
 | 
 cc 
 | 
  
 # Sets the campaign ID to a temporary ID. 
  
 cc 
 . 
 campaign 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
  
 customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 # Sets the keyword theme to the given keyword_theme_info. 
  
 cc 
 . 
 keyword_theme 
  
 = 
  
 info 
  
 end 
  
 end 
  
 end 
  
 # Create a location criterion for each location in the suggestion info object 
  
 # to add corresponding location targeting to the Smart campaign 
  
 suggestion_info 
 . 
 location_list 
 . 
 locations 
 . 
 each 
  
 do 
  
 | 
 location 
 | 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_criterion_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 campaign_criterion 
  
 do 
  
 | 
 cc 
 | 
  
 # Sets the campaign ID to a temporary ID. 
  
 cc 
 . 
 campaign 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
  
 customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 # Sets the location to the given location. 
  
 cc 
 . 
 location 
  
 = 
  
 location 
  
 end 
  
 end 
  
 end 
  
 operations 
 end 
 # Creates a mutate_operation that creates a new ad group. 
 # A temporary ID will be used in the campaign resource name for this 
 # ad group to associate it with the Smart campaign created in earlier steps. 
 # A temporary ID will also be used for its own resource name so that we can 
 # associate an ad group ad with it later in the process. 
 # Only one ad group can be created for a given Smart campaign. 
 def 
  
 create_ad_group_operation 
 ( 
 client 
 , 
  
 customer_id 
 ) 
  
 mutate_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 ad_group_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 ad_group 
  
 do 
  
 | 
 ag 
 | 
  
 # Set the ad group ID to a temporary ID. 
  
 ag 
 . 
 resource_name 
  
 = 
  
 client 
 . 
 path 
 . 
 ad_group 
 ( 
 customer_id 
 , 
  
 AD_GROUP_TEMPORARY_ID 
 ) 
  
 ag 
 . 
 name 
  
 = 
  
 "Smart campaign ad group # 
 #{ 
 ( 
 Time 
 . 
 new 
 . 
 to_f 
  
 * 
  
 1000 
 ) 
 . 
 to_i 
 } 
 " 
  
 # Set the campaign ID to a temporary ID. 
  
 ag 
 . 
 campaign 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
 customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 # The ad group type must be set to SMART_CAMPAIGN_ADS. 
  
 ag 
 . 
 type 
  
 = 
  
 :SMART_CAMPAIGN_ADS 
  
 end 
  
 end 
  
 mutate_operation 
 end 
 # Creates a mutate_operation that creates a new ad group ad. 
 # A temporary ID will be used in the ad group resource name for this 
 # ad group ad to associate it with the ad group created in earlier steps. 
 def 
  
 create_ad_group_ad_operation 
 ( 
 client 
 , 
  
 customer_id 
 , 
  
 ad_suggestions 
 ) 
  
 mutate_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 ad_group_ad_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 ad_group_ad 
  
 do 
  
 | 
 aga 
 | 
  
 # Set the ad group ID to a temporary ID. 
  
 aga 
 . 
 ad_group 
  
 = 
  
 client 
 . 
 path 
 . 
 ad_group 
 ( 
 customer_id 
 , 
  
 AD_GROUP_TEMPORARY_ID 
 ) 
  
 aga 
 . 
 ad 
  
 = 
  
 client 
 . 
 resource 
 . 
 ad 
  
 do 
  
 | 
 ad 
 | 
  
 # Set the type to SMART_CAMPAIGN_AD. 
  
 ad 
 . 
 type 
  
 = 
  
 :SMART_CAMPAIGN_AD 
  
 ad 
 . 
 smart_campaign_ad 
  
 = 
  
 client 
 . 
 resource 
 . 
 smart_campaign_ad_info 
  
 do 
  
 | 
 sca 
 | 
  
 # The SmartCampaignAdInfo object includes headlines and descriptions 
  
 # retrieved from the SmartCampaignSuggestService.SuggestSmartCampaignAd 
  
 # method. It's recommended that users review and approve or update these 
  
 # creatives before they're set on the ad. It's possible that some or all of 
  
 # these assets may contain empty texts, which should not be set on the ad 
  
 # and instead should be replaced with meaningful texts from the user. Below 
  
 # we just accept the creatives that were suggested while filtering out empty 
  
 # assets. If no headlines or descriptions were suggested, then we manually 
  
 # add some, otherwise this operation will generate an INVALID_ARGUMENT 
  
 # error. Individual workflows will likely vary here. 
  
 sca 
 . 
 headlines 
  
 += 
  
 ad_suggestions 
 . 
 headlines 
 . 
 filter 
 ( 
& :text 
 ) 
  
 if 
  
 ad_suggestions 
  
 if 
  
 sca 
 . 
 headlines 
 . 
 size 
 < 
 REQUIRED_NUM_HEADLINES 
  
 ( 
 REQUIRED_NUM_HEADLINES 
  
 - 
  
 sca 
 . 
 headlines 
 . 
 size 
 ) 
 . 
 times 
  
 do 
  
 | 
 i 
 | 
  
 sca 
 . 
 headlines 
 << 
 client 
 . 
 resource 
 . 
 ad_text_asset 
  
 do 
  
 | 
 asset 
 | 
  
 asset 
 . 
 text 
  
 = 
  
 "placeholder headline 
 #{ 
 i 
 } 
 " 
  
 end 
  
 end 
  
 end 
  
 sca 
 . 
 descriptions 
  
 += 
  
 ad_suggestions 
 . 
 descriptions 
 . 
 filter 
 ( 
& :text 
 ) 
  
 if 
  
 ad_suggestions 
  
 if 
  
 sca 
 . 
 descriptions 
 . 
 size 
 < 
 REQUIRED_NUM_DESCRIPTIONS 
  
 ( 
 REQUIRED_NUM_DESCRIPTIONS 
  
 - 
  
 sca 
 . 
 descriptions 
 . 
 size 
 ) 
 . 
 times 
  
 do 
  
 | 
 i 
 | 
  
 sca 
 . 
 descriptions 
 << 
 client 
 . 
 resource 
 . 
 ad_text_asset 
  
 do 
  
 | 
 asset 
 | 
  
 asset 
 . 
 text 
  
 = 
  
 "placeholder description 
 #{ 
 i 
 } 
 " 
  
 end 
  
 end 
  
 end 
  
 end 
  
 end 
  
 end 
  
 end 
  
 mutate_operation 
 end 
 # Prints the details of a mutate_google_ads_response. 
 # Parses the "response" oneof field name and uses it to extract the new 
 # entity's name and resource name. 
 def 
  
 print_response_details 
 ( 
 response 
 ) 
  
 # Parse the mutate response to print details about the entities that 
  
 # were created by the request. 
  
 response 
 . 
 mutate_operation_responses 
 . 
 each 
  
 do 
  
 | 
 result 
 | 
  
 resource_type 
  
 = 
  
 "unrecognized" 
  
 resource_name 
  
 = 
  
 "not found" 
  
 resource_type 
 , 
  
 resource_name 
  
 = 
  
 if 
  
 result 
 . 
 campaign_budget_result 
  
 [ 
 "campaign_budget" 
 , 
  
 result 
 . 
 campaign_budget_result 
 . 
 resource_name 
 ] 
  
 elsif 
  
 result 
 . 
 campaign_result 
  
 [ 
 "campaign" 
 , 
  
 result 
 . 
 campaign_result 
 . 
 resource_name 
 ] 
  
 elsif 
  
 result 
 . 
 smart_campaign_setting_result 
  
 [ 
 "smart_campaign_setting" 
 , 
  
 result 
 . 
 smart_campaign_setting_result 
 . 
 resource_name 
 ] 
  
 elsif 
  
 result 
 . 
 campaign_criterion_result 
  
 [ 
 "campaign_criterion" 
 , 
  
 result 
 . 
 campaign_criterion_result 
 . 
 resource_name 
 ] 
  
 elsif 
  
 result 
 . 
 ad_group_result 
  
 [ 
 "ad_group" 
 , 
  
 result 
 . 
 ad_group_result 
 . 
 resource_name 
 ] 
  
 elsif 
  
 result 
 . 
 ad_group_ad_result 
  
 [ 
 "ad_group_ad" 
 , 
  
 result 
 . 
 ad_group_ad_result 
 . 
 resource_name 
 ] 
  
 end 
  
 puts 
  
 "Created a(n) 
 #{ 
 resource_type 
 } 
 with resource name: ' 
 #{ 
 resource_name 
 } 
 '" 
  
 end 
 end 
 if 
  
 __FILE__ 
  
 == 
  
 $0 
  
 # Geo target constant for New York City. 
  
 GEO_TARGET_CONSTANT 
  
 = 
  
 "1023191" 
  
 # Country code is a two-letter ISO-3166 code, for a list of all codes see: 
  
 # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-16 
  
 COUNTRY_CODE 
  
 = 
  
 "US" 
  
 # For a list of all language codes, see: 
  
 # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 
  
 LANGUAGE_CODE 
  
 = 
  
 "en" 
  
 LANDING_PAGE_URL 
  
 = 
  
 "http://www.example.com" 
  
 PHONE_NUMBER 
  
 = 
  
 "800-555-0100" 
  
 BUDGET_TEMPORARY_ID 
  
 = 
  
 "-1" 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
  
 = 
  
 "-2" 
  
 AD_GROUP_TEMPORARY_ID 
  
 = 
  
 "-3" 
  
 # These define the minimum number of headlines and descriptions that are 
  
 # required to create an AdGroupAd in a Smart campaign. 
  
 REQUIRED_NUM_HEADLINES 
  
 = 
  
 3 
  
 REQUIRED_NUM_DESCRIPTIONS 
  
 = 
  
 2 
  
 options 
  
 = 
  
 {} 
  
 # The following parameter(s) should be provided to run the example. You can 
  
 # either specify these by changing the INSERT_XXX_ID_HERE values below, or on 
  
 # the command line. 
  
 # 
  
 # Parameters passed on the command line will override any parameters set in 
  
 # code. 
  
 # 
  
 # Running the example with -h will print the command line usage. 
  
 options 
 [ 
 :customer_id 
 ] 
  
 = 
  
 'INSERT_CUSTOMER_ID_HERE' 
  
 OptionParser 
 . 
 new 
  
 do 
  
 | 
 opts 
 | 
  
 opts 
 . 
 banner 
  
 = 
  
 sprintf 
 ( 
 'Usage: %s [options]' 
 , 
  
 File 
 . 
 basename 
 ( 
 __FILE__ 
 )) 
  
 opts 
 . 
 separator 
  
 '' 
  
 opts 
 . 
 separator 
  
 'Options:' 
  
 opts 
 . 
 on 
 ( 
 '-C' 
 , 
  
 '--customer-id CUSTOMER-ID' 
 , 
  
 String 
 , 
  
 'Customer ID' 
 ) 
  
 do 
  
 | 
 v 
 | 
  
 options 
 [ 
 :customer_id 
 ] 
  
 = 
  
 v 
  
 end 
  
 opts 
 . 
 on 
 ( 
 '-k' 
 , 
  
 '--keyword-text KEYWORD-TEXT' 
 , 
  
 String 
 , 
  
 'A keyword text used to retrieve keyword theme constant ' 
  
 \ 
  
 'suggestions from the KeywordThemeConstantService. These keyword ' 
  
 \ 
  
 'theme suggestions are generated using auto-completion data for ' 
  
 \ 
  
 'the given text and may help improve the performance of ' 
  
 \ 
  
 'the Smart campaign.' 
 ) 
  
 do 
  
 | 
 v 
 | 
  
 options 
 [ 
 :keyword_text 
 ] 
  
 = 
  
 v 
  
 end 
  
 opts 
 . 
 on 
 ( 
 '-f' 
 , 
  
 '--freeform-keyword-text FREEFORM-KEYWORD-TEXT' 
 , 
  
 String 
 , 
  
 'A keyword text used to create a freeform keyword theme, which is ' 
  
 \ 
  
 'entirely user-specified and not derived from any suggestion ' 
  
 \ 
  
 'service. Using free-form keyword themes is typically not ' 
  
 \ 
  
 'recommended because they are less effective than suggested ' 
  
 \ 
  
 'keyword themes, however they are useful in situations where a ' 
  
 \ 
  
 'very specific term needs to be targeted.' 
 ) 
  
 do 
  
 | 
 v 
 | 
  
 options 
 [ 
 :free_form_keyword_text 
 ] 
  
 = 
  
 v 
  
 end 
  
 opts 
 . 
 on 
 ( 
 '-b' 
 , 
  
 '--business-profile-location BUSINESS-PROFILE-LOCATION' 
 , 
  
 String 
 , 
  
 'The resource name of a Business Profile location. This is required' 
  
 \ 
  
 ' if a business name is not provided. It can be retrieved using the' 
  
 \ 
  
 ' GMB API, for details see:' 
  
 \ 
  
 ' https://developers.google.com/my-business/reference/businessinformation/rest/v1/accounts.locations' 
  
 \ 
  
 ' or from the Business Profile UI (https://support.google.com/business/answer/10737668).' 
 ) 
  
 do 
  
 | 
 v 
 | 
  
 options 
 [ 
 :business_profile_location 
 ] 
  
 = 
  
 v 
  
 end 
  
 opts 
 . 
 on 
 ( 
 '-n' 
 , 
  
 '--business-name BUSINESS-NAME' 
 , 
  
 String 
 , 
  
 'The name of a Business Profile business. This is required' 
  
 \ 
  
 ' if a business location ID is not provided.' 
 ) 
  
 do 
  
 | 
 v 
 | 
  
 options 
 [ 
 :business_name 
 ] 
  
 = 
  
 v 
  
 end 
  
 opts 
 . 
 separator 
  
 '' 
  
 opts 
 . 
 separator 
  
 'Help:' 
  
 opts 
 . 
 on_tail 
 ( 
 '-h' 
 , 
  
 '--help' 
 , 
  
 'Show this message' 
 ) 
  
 do 
  
 puts 
  
 opts 
  
 exit 
  
 end 
  
 end 
 . 
 parse! 
  
 begin 
  
 add_smart_campaign 
 ( 
  
 options 
 . 
 fetch 
 ( 
 :customer_id 
 ) 
 . 
 tr 
 ( 
 "-" 
 , 
  
 "" 
 ), 
  
 options 
 [ 
 :keyword_text 
 ] 
 , 
  
 options 
 [ 
 :free_form_keyword_text 
 ] 
 , 
  
 options 
 [ 
 :business_profile_location 
 ] 
 , 
  
 options 
 [ 
 :business_name 
 ] 
 , 
  
 ) 
  
 rescue 
  
 Google 
 :: 
 Ads 
 :: 
 GoogleAds 
 :: 
 Errors 
 :: 
 GoogleAdsError 
  
 = 
>  
 e 
  
 e 
 . 
 failure 
 . 
 errors 
 . 
 each 
  
 do 
  
 | 
 error 
 | 
  
 STDERR 
 . 
 printf 
 ( 
 "Error with message: %s 
 \n 
 " 
 , 
  
 error 
 . 
 message 
 ) 
  
 if 
  
 error 
 . 
 location 
  
 error 
 . 
 location 
 . 
 field_path_elements 
 . 
 each 
  
 do 
  
 | 
 field_path_element 
 | 
  
 STDERR 
 . 
 printf 
 ( 
 " 
 \t 
 On field: %s 
 \n 
 " 
 , 
  
 field_path_element 
 . 
 field_name 
 ) 
  
 end 
  
 end 
  
 error 
 . 
 error_code 
 . 
 to_h 
 . 
 each 
  
 do 
  
 | 
 k 
 , 
  
 v 
 | 
  
 next 
  
 if 
  
 v 
  
 == 
  
 :UNSPECIFIED 
  
 STDERR 
 . 
 printf 
 ( 
 " 
 \t 
 Type: %s 
 \n\t 
 Code: %s 
 \n 
 " 
 , 
  
 k 
 , 
  
 v 
 ) 
  
 end 
  
 end 
  
 raise 
  
 end 
 end 
  
  

Perl

 #!/usr/bin/perl -w 
 # 
 # Copyright 2021, 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. 
 # 
 # This example shows how to create a Smart campaign. 
 # 
 # More details on Smart campaigns can be found here: 
 # https://support.google.com/google-ads/answer/7652860 
 use 
  
 strict 
 ; 
 use 
  
 warnings 
 ; 
 use 
  
 utf8 
 ; 
 use 
  
 FindBin 
  
 qw($Bin) 
 ; 
 use 
  
 lib 
  
 "$Bin/../../lib" 
 ; 
 use 
  
 Google::Ads::GoogleAds::Client 
 ; 
 use 
  
 Google::Ads::GoogleAds::Utils::GoogleAdsHelper 
 ; 
 use 
  
 Google::Ads::GoogleAds::Utils::FieldMasks 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::Ad 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::AdGroup 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::AdGroupAd 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::CampaignBudget 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::Campaign 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::CampaignCriterion 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::PhoneNumber 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::SmartCampaignSetting 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::AdScheduleInfo 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::KeywordThemeInfo 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::LocationInfo 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::SmartCampaignAdInfo 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::AdTextAsset 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::AdGroupTypeEnum 
  
 qw(SMART_CAMPAIGN_ADS) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::AdTypeEnum 
  
 qw(SMART_CAMPAIGN_AD) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::AdvertisingChannelTypeEnum 
  
 qw(SMART) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::AdvertisingChannelSubTypeEnum 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::BudgetTypeEnum 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::CampaignStatusEnum 
  
 qw(PAUSED) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::DayOfWeekEnum 
  
 qw(MONDAY) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::MinuteOfHourEnum 
  
 qw(ZERO) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::ProximityRadiusUnitsEnum 
  
 qw(MILES) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::EuPoliticalAdvertisingStatusEnum 
  
 qw(DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::AdGroupService::AdGroupOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::AdGroupAdService::AdGroupAdOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::CampaignBudgetService::CampaignBudgetOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::CampaignService::CampaignOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::CampaignCriterionService::CampaignCriterionOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService::MutateOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::KeywordThemeConstantService::SuggestKeywordThemeConstantsRequest 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSettingService::SmartCampaignSettingOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService::BusinessContext 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService::KeywordTheme 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService::LocationList 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService::SmartCampaignSuggestionInfo 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService::SuggestKeywordThemesRequest 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService::SuggestSmartCampaignAdRequest 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService::SuggestSmartCampaignBudgetOptionsRequest 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames 
 ; 
 use 
  
 Getopt::Long 
  
 qw(:config auto_help) 
 ; 
 use 
  
 Pod::Usage 
 ; 
 use 
  
 Cwd 
  
 qw(abs_path) 
 ; 
 use 
  
 Data::Uniqid 
  
 qw(uniqid) 
 ; 
 # Geo target constant for New York City. 
 use 
  
 constant 
  
 GEO_TARGET_CONSTANT 
  
 = 
>  
 1023191 
 ; 
 # Country code is a two-letter ISO-3166 code, for a list of all codes see: 
 # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-16 
 use 
  
 constant 
  
 COUNTRY_CODE 
  
 = 
>  
 "US" 
 ; 
 # For a list of all language codes, see: 
 # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 
 use 
  
 constant 
  
 LANGUAGE_CODE 
  
 = 
>  
 "en" 
 ; 
 use 
  
 constant 
  
 LANDING_PAGE_URL 
  
 = 
>  
 "http://www.example.com" 
 ; 
 use 
  
 constant 
  
 PHONE_NUMBER 
  
 = 
>  
 "800-555-0100" 
 ; 
 use 
  
 constant 
  
 BUDGET_TEMPORARY_ID 
  
 = 
>  
 - 
 1 
 ; 
 use 
  
 constant 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
  
 = 
>  
 - 
 2 
 ; 
 use 
  
 constant 
  
 AD_GROUP_TEMPORARY_ID 
  
 = 
>  
 - 
 3 
 ; 
 # These define the minimum number of headlines and descriptions that are 
 # required to create an AdGroupAd in a Smart campaign. 
 use 
  
 constant 
  
 REQUIRED_NUM_HEADLINES 
  
 = 
>  
 3 
 ; 
 use 
  
 constant 
  
 REQUIRED_NUM_DESCRIPTIONS 
  
 = 
>  
 2 
 ; 
 # The following parameter(s) should be provided to run the example. You can 
 # either specify these by changing the INSERT_XXX_ID_HERE values below, or on 
 # the command line. 
 # 
 # Parameters passed on the command line will override any parameters set in 
 # code. 
 # 
 # Running the example with -h will print the command line usage. 
 my 
  
 $customer_id 
  
 = 
  
 undef 
 ; 
 my 
  
 $keyword_text 
  
 = 
  
 undef 
 ; 
 my 
  
 $free_form_keyword_text 
  
 = 
  
 undef 
 ; 
 my 
  
 $business_profile_location 
  
 = 
  
 undef 
 ; 
 my 
  
 $business_name 
  
 = 
  
 undef 
 ; 
 sub 
  
 add_smart_campaign 
  
 { 
  
 my 
  
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $keyword_text 
 , 
  
 $free_form_keyword_text 
 , 
  
 $business_profile_location 
 , 
  
 $business_name 
 ) 
  
 = 
  
 @_ 
 ; 
  
 # The SmartCampaignSuggestionInfo object acts as the basis for many of the 
  
 # entities necessary to create a Smart campaign. It will be reused a number 
  
 # of times to retrieve suggestions for keyword themes, budget amount, 
  
 # ad creatives, and campaign criteria. 
  
 my 
  
 $suggestion_info 
  
 = 
  
 _get_smart_campaign_suggestion_info 
 ( 
 $business_profile_location 
 , 
  
 $business_name 
 ); 
  
 # After creating a SmartCampaignSuggestionInfo object we first use it to 
  
 # generate a list of keyword themes using the SuggestKeywordThemes method 
  
 # on the SmartCampaignSuggestService. It is strongly recommended that you 
  
 # use this strategy for generating keyword themes. 
  
 my 
  
 $keyword_themes 
  
 = 
  
 _get_keyword_theme_suggestions 
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $suggestion_info 
 ); 
  
 # If a keyword text is given, retrieve keyword theme constant suggestions 
  
 # from the KeywordThemeConstantService, map them to KeywordThemes, and 
  
 # append them to the existing list. This logic should ideally only be used 
  
 # if the suggestions from the get_keyword_theme_suggestions funtion are 
  
 # insufficient. 
  
 if 
  
 ( 
 defined 
  
 $keyword_text 
 ) 
  
 { 
  
 push 
  
 @$keyword_themes 
 , 
  
 @ 
 { 
 _get_keyword_text_auto_completions 
 ( 
 $api_client 
 , 
  
 $keyword_text 
 )}; 
  
 } 
  
 # Map the KeywordThemeConstants retrieved by the previous two steps to 
  
 # KeywordThemeInfo instances. 
  
 my 
  
 $keyword_theme_infos 
  
 = 
  
 _map_keyword_themes_to_keyword_infos 
 ( 
 $keyword_themes 
 ); 
  
 # If a free-form keyword text is given we create a KeywordThemeInfo instance 
  
 # from it and add it to the existing list. 
  
 if 
  
 ( 
 defined 
  
 $free_form_keyword_text 
 ) 
  
 { 
  
 push 
  
 @$keyword_theme_infos 
 , 
  
 _get_free_form_keyword_theme_info 
 ( 
 $free_form_keyword_text 
 ); 
  
 } 
  
 # Now add the generated keyword themes to the suggestion info instance. 
  
 $suggestion_info 
 - 
> { 
 keywordThemes 
 } 
  
 = 
  
 $keyword_theme_infos 
 ; 
  
 # Retrieve a budget amount suggestion. 
  
 my 
  
 $suggested_budget_amount 
  
 = 
  
 _get_budget_suggestion 
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $suggestion_info 
 ); 
  
 # Retrieve Smart campaign ad creative suggestions. 
  
 my 
  
 $ad_suggestions 
  
 = 
  
 _get_ad_suggestions 
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $suggestion_info 
 ); 
  
 # The below methods create and return MutateOperations that we later provide to the 
  
 # GoogleAdsService.Mutate method in order to create the entities in a single 
  
 # request. Since the entities for a Smart campaign are closely tied to one-another 
  
 # it's considered a best practice to create them in a single Mutate request; the 
  
 # entities will either all complete successfully or fail entirely, leaving no 
  
 # orphaned entities. See: 
  
 # https://developers.google.com/google-ads/api/docs/mutating/overview 
  
 my 
  
 $campaign_budget_operation 
  
 = 
  
 _create_campaign_budget_operation 
 ( 
 $customer_id 
 , 
  
 $suggested_budget_amount 
 ); 
  
 my 
  
 $smart_campaign_operation 
  
 = 
  
 _create_smart_campaign_operation 
 ( 
 $customer_id 
 ); 
  
 my 
  
 $smart_campaign_setting_operation 
  
 = 
  
 _create_smart_campaign_setting_operation 
 ( 
 $customer_id 
 , 
  
 $business_profile_location 
 , 
  
 $business_name 
 ); 
  
 my 
  
 $campaign_criterion_operations 
  
 = 
  
 _create_campaign_criterion_operations 
 ( 
 $customer_id 
 , 
  
 $keyword_theme_infos 
 , 
  
 $suggestion_info 
 ); 
  
 my 
  
 $ad_group_operation 
  
 = 
  
 _create_ad_group_operation 
 ( 
 $customer_id 
 ); 
  
 my 
  
 $ad_group_ad_operation 
  
 = 
  
 _create_ad_group_ad_operation 
 ( 
 $customer_id 
 , 
  
 $ad_suggestions 
 ); 
  
 # It's important to create these entities in this order because they depend on 
  
 # each other. For example, the SmartCampaignSetting and ad group depend on the 
  
 # campaign and the ad group ad depends on the ad group. 
  
 my 
  
 $mutate_operations 
  
 = 
  
 [ 
  
 $campaign_budget_operation 
 , 
  
 $smart_campaign_operation 
 , 
  
 $smart_campaign_setting_operation 
 , 
  
 # Expand the list of campaign criterion operations into the list of 
  
 # other mutate operations. 
  
 @$campaign_criterion_operations 
 , 
  
 $ad_group_operation 
 , 
  
 $ad_group_ad_operation 
  
 ]; 
  
 # Send the operations in a single mutate request. 
  
 my 
  
 $mutate_google_ads_response 
  
 = 
  
 $api_client 
 - 
> GoogleAdsService 
 () 
 - 
> mutate 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id 
 , 
  
 mutateOperations 
  
 = 
>  
 $mutate_operations 
  
 }); 
  
 _print_response_details 
 ( 
 $mutate_google_ads_response 
 ); 
  
 return 
  
 1 
 ; 
 } 
 # Retrieves KeywordThemes using the given suggestion info. 
 # Here we use the SuggestKeywordThemes method, which uses all of the business 
 # details included in the given SmartCampaignSuggestionInfo instance to generate 
 # keyword theme suggestions. This is the recommended way to generate keyword themes 
 # because it uses detailed information about your business, its location, and 
 # website content to generate keyword themes. 
 sub 
  
 _get_keyword_theme_suggestions 
  
 { 
  
 my 
  
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $suggestion_info 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $response 
  
 = 
  
 $api_client 
 - 
> SmartCampaignSuggestService 
 () 
 - 
> suggest_keyword_themes 
 ( 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService:: 
 SuggestKeywordThemesRequest 
  
 - 
> new 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id 
 , 
  
 suggestionInfo 
  
 = 
>  
 $suggestion_info 
  
 })); 
  
 printf 
  
 "Retrieved %d keyword theme suggestions from the SuggestKeywordThemes" 
  
 . 
  
 "method.\n" 
 , 
  
 scalar 
  
 @ 
 { 
 $response 
 - 
> { 
 keywordThemes 
 }}; 
  
 return 
  
 $response 
 - 
> { 
 keywordThemes 
 }; 
 } 
 # Retrieves KeywordThemeConstants for the given keyword text. 
 # These KeywordThemeConstants are derived from autocomplete data for the given 
 # keyword text. They are mapped to KeywordThemes before being returned. 
 sub 
  
 _get_keyword_text_auto_completions 
  
 { 
  
 my 
  
 ( 
 $api_client 
 , 
  
 $keyword_text 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $response 
  
 = 
  
 $api_client 
 - 
> KeywordThemeConstantService 
 () 
 - 
> suggest 
 ( 
  
 Google::Ads::GoogleAds::V21::Services::KeywordThemeConstantService:: 
 SuggestKeywordThemeConstantsRequest 
  
 - 
> new 
 ({ 
  
 queryText 
  
 = 
>  
 $keyword_text 
 , 
  
 countryCode 
  
 = 
>  
 COUNTRY_CODE 
 , 
  
 languageCode 
  
 = 
>  
 LANGUAGE_CODE 
  
 })); 
  
 printf 
  
 "Retrieved %d keyword theme constants using the keyword '%s'.\n" 
 , 
  
 scalar 
  
 @ 
 { 
 $response 
 - 
> { 
 keywordThemeConstants 
 }}, 
  
 $keyword_text 
 ; 
  
 # Map the keyword theme constants to KeywordTheme instances for consistency 
  
 # with the response from SmartCampaignSuggestService.SuggestKeywordThemes. 
  
 my 
  
 $keyword_themes 
  
 = 
  
 [] 
 ; 
  
 foreach 
  
 my 
  
 $keyword_theme_constant 
  
 ( 
 @ 
 { 
 $response 
 - 
> { 
 keywordThemeConstants 
 }}) 
  
 { 
  
 push 
  
 @$keyword_themes 
 , 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService:: 
 KeywordTheme 
  
 - 
> new 
 ({ 
  
 keywordThemeConstant 
  
 = 
>  
 $keyword_theme_constant 
  
 }); 
  
 } 
  
 return 
  
 $keyword_themes 
 ; 
 } 
 # Creates a KeywordInfo instance using the given free-form keyword text. 
 sub 
  
 _get_free_form_keyword_theme_info 
  
 { 
  
 my 
  
 ( 
 $free_form_keyword_text 
 ) 
  
 = 
  
 @_ 
 ; 
  
 return 
  
 Google::Ads::GoogleAds::V21::Common:: 
 KeywordThemeInfo 
 - 
> new 
 ({ 
  
 freeFormKeywordTheme 
  
 = 
>  
 $free_form_keyword_text 
  
 }); 
 } 
 # Maps a list of KeywordThemes to KeywordThemeInfos. 
 sub 
  
 _map_keyword_themes_to_keyword_infos 
  
 { 
  
 my 
  
 ( 
 $keyword_themes 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $keyword_theme_infos 
  
 = 
  
 [] 
 ; 
  
 foreach 
  
 my 
  
 $keyword_theme 
  
 ( 
 @$keyword_themes 
 ) 
  
 { 
  
 if 
  
 ( 
 defined 
  
 $keyword_theme 
 - 
> { 
 keywordThemeConstant 
 }) 
  
 { 
  
 push 
  
 @$keyword_theme_infos 
 , 
  
 Google::Ads::GoogleAds::V21::Common:: 
 KeywordThemeInfo 
 - 
> new 
 ({ 
  
 keywordThemeConstant 
  
 = 
>  
 $keyword_theme 
 - 
> { 
 keywordThemeConstant 
 }{ 
 resourceName 
 }}); 
  
 } 
  
 elsif 
  
 ( 
 defined 
  
 $keyword_theme 
 - 
> { 
 freeFormKeywordTheme 
 }) 
  
 { 
  
 push 
  
 @$keyword_theme_infos 
 , 
  
 Google::Ads::GoogleAds::V21::Common:: 
 KeywordThemeInfo 
 - 
> new 
 ({ 
  
 freeFormKeywordTheme 
  
 = 
>  
 $keyword_theme 
 - 
> { 
 freeFormKeywordTheme 
 }}); 
  
 } 
  
 else 
  
 { 
  
 die 
  
 "A malformed KeywordTheme was encountered: $keyword_theme" 
 ; 
  
 } 
  
 } 
  
 return 
  
 $keyword_theme_infos 
 ; 
 } 
 # Builds a SmartCampaignSuggestionInfo object with business details. 
 # The details are used by the SmartCampaignSuggestService to suggest a budget 
 # amount as well as creatives for the ad. 
 # Note that when retrieving ad creative suggestions you must set the 
 # "final_url", "language_code" and "keyword_themes" fields on the 
 # SmartCampaignSuggestionInfo instance. 
 sub 
  
 _get_smart_campaign_suggestion_info 
  
 { 
  
 my 
  
 ( 
 $business_profile_location 
 , 
  
 $business_name 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $suggestion_info 
  
 = 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService:: 
 SmartCampaignSuggestionInfo 
  
 - 
> new 
 ({ 
  
 # Add the URL of the campaign's landing page. 
  
 finalUrl 
  
 = 
>  
 LANDING_PAGE_URL 
 , 
  
 # Add the language code for the campaign. 
  
 languageCode 
  
 = 
>  
 LANGUAGE_CODE 
 , 
  
 # Construct location information using the given geo target constant. 
  
 # It's also possible to provide a geographic proximity using the 
  
 # "proximity" field on suggestion_info, for example: 
  
 # 
  
 # proximity => Google::Ads::GoogleAds::V21::Common::ProximityInfo->new({ 
  
 #     address => Google::Ads::GoogleAds::V21::Common::AddressInfo->new({ 
  
 #         postalCode     => "INSERT_POSTAL_CODE", 
  
 #         provinceCode   => "INSERT_PROVINCE_CODE", 
  
 #         countryCode    => "INSERT_COUNTRY_CODE", 
  
 #         provinceName   => "INSERT_PROVINCE_NAME", 
  
 #         streetAddress  => "INSERT_STREET_ADDRESS", 
  
 #         streetAddress2 => "INSERT_STREET_ADDRESS_2", 
  
 #         cityName       => "INSERT_CITY_NAME" 
  
 #       } 
  
 #     ), 
  
 #     radius      => "INSERT_RADIUS", 
  
 #     radiusUnits => MILES 
  
 #   } 
  
 # ), 
  
 # 
  
 # For more information on proximities see: 
  
 # https://developers.google.com/google-ads/api/reference/rpc/latest/ProximityInfo 
  
 locationList 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService:: 
 LocationList 
  
 - 
> new 
 ( 
  
 )}); 
  
 # Add the LocationInfo object to the list of locations on the SuggestionInfo 
  
 # object. You have the option of providing multiple locations when using 
  
 # location-based suggestions. 
  
 push 
  
 @ 
 { 
 $suggestion_info 
 - 
> { 
 locationList 
 }{ 
 locations 
 }}, 
  
 Google::Ads::GoogleAds::V21::Common:: 
 LocationInfo 
 - 
> new 
 ({ 
  
 # Set the location to the resource name of the given geo target constant. 
  
 geoTargetConstant 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 geo_target_constant 
 ( 
  
 GEO_TARGET_CONSTANT 
 )}); 
  
 # Set one of the business_profile_location or business_name, whichever is provided. 
  
 if 
  
 ( 
 defined 
  
 $business_profile_location 
 ) 
  
 { 
  
 $suggestion_info 
 - 
> { 
 businessProfileLocation 
 } 
  
 = 
  
 _convert_business_profile_location 
 ( 
 $business_profile_location 
 ); 
  
 } 
  
 else 
  
 { 
  
 $suggestion_info 
 - 
> { 
 businessContext 
 } 
  
 = 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService:: 
 BusinessContext 
  
 - 
> new 
 ({ 
  
 businessName 
  
 = 
>  
 $business_name 
  
 }); 
  
 } 
  
 # Add a schedule detailing which days of the week the business is open. This 
  
 # example schedule describes a business that is open on Mondays from 9:00 AM 
  
 # to 5:00 PM. 
  
 push 
  
 @ 
 { 
 $suggestion_info 
 - 
> { 
 adSchedules 
 }}, 
  
 Google::Ads::GoogleAds::V21::Common:: 
 AdScheduleInfo 
 - 
> new 
 ({ 
  
 # Set the day of this schedule as Monday. 
  
 dayOfWeek 
  
 = 
>  
 MONDAY 
 , 
  
 # Set the start hour to 9 AM. 
  
 startHour 
  
 = 
>  
 9 
 , 
  
 # Set the end hour to 5 PM. 
  
 endHour 
  
 = 
>  
 17 
 , 
  
 # Set the start and end minutes to zero. 
  
 startMinute 
  
 = 
>  
 ZERO 
 , 
  
 endMinute 
  
 = 
>  
 ZERO 
  
 }); 
  
 return 
  
 $suggestion_info 
 ; 
 } 
 # Retrieves a suggested budget amount for a new budget. 
 # Using the SmartCampaignSuggestService to determine a daily budget for new and 
 # existing Smart campaigns is highly recommended because it helps the campaigns 
 # achieve optimal performance. 
 sub 
  
 _get_budget_suggestion 
  
 { 
  
 my 
  
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $suggestion_info 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $request 
  
 = 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService:: 
 SuggestSmartCampaignBudgetOptionsRequest 
  
 - 
> new 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id 
 , 
  
 # You can retrieve suggestions for an existing campaign by setting the 
  
 # "campaign" field of the request to the resource name of a campaign and 
  
 # leaving the rest of the request fields below unset: 
  
 # campaign => "INSERT_CAMPAIGN_RESOURCE_NAME_HERE", 
  
 # 
  
 # Since these suggestions are for a new campaign, we're going to use the 
  
 # "suggestion_info" field instead. 
  
 suggestionInfo 
  
 = 
>  
 $suggestion_info 
  
 }); 
  
 # Issue a request to retrieve a budget suggestion. 
  
 my 
  
 $response 
  
 = 
  
 $api_client 
 - 
> SmartCampaignSuggestService 
 () 
  
 - 
> suggest_smart_campaign_budget_options 
 ( 
 $request 
 ); 
  
 # Three tiers of options will be returned: "low", "high", and "recommended". 
  
 # Here we will use the "recommended" option. The amount is specified in micros, 
  
 # where one million is equivalent to one currency unit. 
  
 printf 
  
 "A daily budget amount of %d was suggested, garnering an estimated " 
  
 . 
  
 "minimum of %d clicks and an estimated maximum of %d clicks per day.\n" 
 , 
  
 $response 
 - 
> { 
 recommended 
 }{ 
 dailyAmountMicros 
 }, 
  
 $response 
 - 
> { 
 recommended 
 }{ 
 metrics 
 }{ 
 minDailyClicks 
 }, 
  
 $response 
 - 
> { 
 recommended 
 }{ 
 metrics 
 }{ 
 maxDailyClicks 
 }; 
  
 return 
  
 $response 
 - 
> { 
 recommended 
 }{ 
 dailyAmountMicros 
 }; 
 } 
 # Retrieves creative suggestions for a Smart campaign ad. 
 # Using the SmartCampaignSuggestService to suggest creatives for new and 
 # existing Smart campaigns is highly recommended because it helps the campaigns 
 # achieve optimal performance. 
 sub 
  
 _get_ad_suggestions 
  
 { 
  
 my 
  
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $suggestion_info 
 ) 
  
 = 
  
 @_ 
 ; 
  
 # Issue a request to retrieve ad creative suggestions. 
  
 my 
  
 $response 
  
 = 
  
 $api_client 
 - 
> SmartCampaignSuggestService 
 () 
 - 
> suggest_smart_campaign_ad 
 ( 
  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSuggestService:: 
 SuggestSmartCampaignAdRequest 
  
 - 
> new 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id 
 , 
  
 # Unlike the SuggestSmartCampaignBudgetOptions method, it's only 
  
 # possible to use suggestion_info to retrieve ad creative suggestions. 
  
 suggestionInfo 
  
 = 
>  
 $suggestion_info 
  
 })); 
  
 # The SmartCampaignAdInfo object in the response contains a list of up to 
  
 # three headlines and two descriptions. Note that some of the suggestions 
  
 # may have empty strings as text. Before setting these on the ad you should 
  
 # review them and filter out any empty values. 
  
 my 
  
 $ad_suggestions 
  
 = 
  
 $response 
 - 
> { 
 adInfo 
 }; 
  
 printf 
  
 "The following headlines were suggested:\n" 
 ; 
  
 foreach 
  
 my 
  
 $headline 
  
 ( 
 @ 
 { 
 $ad_suggestions 
 - 
> { 
 headlines 
 }}) 
  
 { 
  
 printf 
  
 "\t%s\n" 
 , 
  
 defined 
  
 $headline 
 - 
> { 
 text 
 } 
  
 ? 
  
 $headline 
 - 
> { 
 text 
 } 
  
 : 
  
 "<None>" 
 ; 
  
 } 
  
 printf 
  
 "And the following descriptions were suggested:\n" 
 ; 
  
 foreach 
  
 my 
  
 $description 
  
 ( 
 @ 
 { 
 $ad_suggestions 
 - 
> { 
 descriptions 
 }}) 
  
 { 
  
 printf 
  
 "\t%s\n" 
 , 
  
 defined 
  
 $description 
 - 
> { 
 text 
 } 
  
 ? 
  
 $description 
 - 
> { 
 text 
 } 
  
 : 
  
 "<None>" 
 ; 
  
 } 
  
 return 
  
 $ad_suggestions 
 ; 
 } 
 # Creates a MutateOperation that creates a new CampaignBudget. 
 # A temporary ID will be assigned to this campaign budget so that it can be 
 # referenced by other objects being created in the same Mutate request. 
 sub 
  
 _create_campaign_budget_operation 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 , 
  
 $suggested_budget_amount 
 ) 
  
 = 
  
 @_ 
 ; 
  
 return 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 campaignBudgetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::CampaignBudgetService:: 
 CampaignBudgetOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 CampaignBudget 
 - 
> new 
 ({ 
  
 name 
  
 = 
>  
 "Smart campaign budget #" 
  
 . 
  
 uniqid 
 (), 
  
 # A budget used for Smart campaigns must have the type SMART_CAMPAIGN. 
  
 type 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Enums::BudgetTypeEnum:: 
 SMART_CAMPAIGN 
 , 
  
 # The suggested budget amount from the SmartCampaignSuggestService is 
  
 # a daily budget. We don't need to specify that here, because the 
  
 # budget period already defaults to DAILY. 
  
 amountMicros 
  
 = 
>  
 $suggested_budget_amount 
 , 
  
 # Set a temporary ID in the budget's resource name so it can be 
  
 # referenced by the campaign in later steps. 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign_budget 
 ( 
  
 $customer_id 
 , 
  
 BUDGET_TEMPORARY_ID 
  
 )})})}); 
 } 
 # Creates a MutateOperation that creates a new Smart campaign. 
 # A temporary ID will be assigned to this campaign so that it can be referenced 
 # by other objects being created in the same Mutate request. 
 sub 
  
 _create_smart_campaign_operation 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 ) 
  
 = 
  
 @_ 
 ; 
  
 return 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 campaignOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::CampaignService:: 
 CampaignOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 Campaign 
 - 
> new 
 ({ 
  
 name 
  
 = 
>  
 "Smart campaign #" 
  
 . 
  
 uniqid 
 (), 
  
 # Set the campaign status as PAUSED. The campaign is the only 
  
 # entity in the mutate request that should have its status set. 
  
 status 
  
 = 
>  
 PAUSED 
 , 
  
 # AdvertisingChannelType must be SMART. 
  
 advertisingChannelType 
  
 = 
>  
 SMART 
 , 
  
 # AdvertisingChannelSubType must be SMART_CAMPAIGN. 
  
 advertisingChannelSubType 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Enums::AdvertisingChannelSubTypeEnum:: 
 SMART_CAMPAIGN 
 , 
  
 # Assign the resource name with a temporary ID. 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 # Declare whether or not this campaign serves political ads targeting the EU. 
  
 # Valid values are CONTAINS_EU_POLITICAL_ADVERTISING and 
  
 # DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING. 
  
 containsEuPoliticalAdvertising 
  
 = 
>  
 DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING 
 , 
  
 # Set the budget using the given budget resource name. 
  
 campaignBudget 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign_budget 
 ( 
  
 $customer_id 
 , 
  
 BUDGET_TEMPORARY_ID 
  
 )})})}); 
 } 
 # Creates a MutateOperation to create a new SmartCampaignSetting. 
 # SmartCampaignSettings are unique in that they only support UPDATE operations, 
 # which are used to update and create them. Below we will use a temporary ID in 
 # the resource name to associate it with the campaign created in the previous step. 
 sub 
  
 _create_smart_campaign_setting_operation 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 , 
  
 $business_profile_location 
 , 
  
 $business_name 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $smart_campaign_setting 
  
 = 
  
 Google::Ads::GoogleAds::V21::Resources:: 
 SmartCampaignSetting 
 - 
> new 
 ({ 
  
 # Set a temporary ID in the campaign setting's resource name to associate it 
  
 # with the campaign created in the previous step. 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 smart_campaign_setting 
 ( 
  
 $customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 # Below we configure the SmartCampaignSetting using many of the same 
  
 # details used to generate a budget suggestion. 
  
 phoneNumber 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 PhoneNumber 
 - 
> new 
 ({ 
  
 countryCode 
  
 = 
>  
 COUNTRY_CODE 
 , 
  
 phoneNumber 
  
 = 
>  
 PHONE_NUMBER 
  
 } 
  
 ), 
  
 finalUrl 
  
 = 
>  
 LANDING_PAGE_URL 
 , 
  
 advertisingLanguageCode 
  
 = 
>  
 LANGUAGE_CODE 
  
 }); 
  
 # It's required that either a business profile location or a business name is 
  
 # added to the SmartCampaignSetting. 
  
 if 
  
 ( 
 defined 
  
 $business_profile_location 
 ) 
  
 { 
  
 $smart_campaign_setting 
 - 
> { 
 businessProfileLocation 
 } 
  
 = 
  
 $business_profile_location 
 ; 
  
 } 
  
 else 
  
 { 
  
 $smart_campaign_setting 
 - 
> { 
 businessName 
 } 
  
 = 
  
 $business_name 
 ; 
  
 } 
  
 return 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 smartCampaignSettingOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::SmartCampaignSettingService:: 
 SmartCampaignSettingOperation 
  
 - 
> new 
 ({ 
  
 update 
  
 = 
>  
 $smart_campaign_setting 
 , 
  
 # Set the update mask on the operation. This is required since the 
  
 # smart campaign setting is created in an UPDATE operation. Here the 
  
 # update mask will be a list of all the fields that were set on the 
  
 # SmartCampaignSetting. 
  
 updateMask 
  
 = 
>  
 all_set_fields_of 
 ( 
 $smart_campaign_setting 
 )})}); 
 } 
 # Creates a list of MutateOperations that create new campaign criteria. 
 sub 
  
 _create_campaign_criterion_operations 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 , 
  
 $keyword_theme_infos 
 , 
  
 $suggestion_info 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $campaign_criterion_operations 
  
 = 
  
 [] 
 ; 
  
 foreach 
  
 my 
  
 $keyword_theme_info 
  
 ( 
 @$keyword_theme_infos 
 ) 
  
 { 
  
 push 
  
 @$campaign_criterion_operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
  
 - 
> new 
 ({ 
  
 campaignCriterionOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::CampaignCriterionService:: 
 CampaignCriterionOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 CampaignCriterion 
 - 
> new 
 ({ 
  
 # Set the campaign ID to a temporary ID. 
  
 campaign 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 # Set the keyword theme to the given KeywordThemeInfo. 
  
 keywordTheme 
  
 = 
>  
 $keyword_theme_info 
  
 })})}); 
  
 } 
  
 # Create a location criterion for each location in the suggestion info object 
  
 # to add corresponding location targeting to the Smart campaign. 
  
 foreach 
  
 my 
  
 $location_info 
  
 ( 
 @ 
 { 
 $suggestion_info 
 - 
> { 
 locationList 
 }{ 
 locations 
 }}) 
  
 { 
  
 push 
  
 @$campaign_criterion_operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
  
 - 
> new 
 ({ 
  
 campaignCriterionOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::CampaignCriterionService:: 
 CampaignCriterionOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 CampaignCriterion 
 - 
> new 
 ({ 
  
 # Set the campaign ID to a temporary ID. 
  
 campaign 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 # Set the location to the given location. 
  
 location 
  
 = 
>  
 $location_info 
  
 })})}); 
  
 } 
  
 return 
  
 $campaign_criterion_operations 
 ; 
 } 
 # Creates a MutateOperation that creates a new ad group. 
 # A temporary ID will be used in the campaign resource name for this ad group to 
 # associate it with the Smart campaign created in earlier steps. A temporary ID 
 # will also be used for its own resource name so that we can associate an ad group ad 
 # with it later in the process. 
 # Only one ad group can be created for a given Smart campaign. 
 sub 
  
 _create_ad_group_operation 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 ) 
  
 = 
  
 @_ 
 ; 
  
 return 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 adGroupOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AdGroupService:: 
 AdGroupOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AdGroup 
 - 
> new 
 ({ 
  
 # Set the ad group ID to a temporary ID. 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 ad_group 
 ( 
  
 $customer_id 
 , 
  
 AD_GROUP_TEMPORARY_ID 
  
 ), 
  
 name 
  
 = 
>  
 "Smart campaign ad group #" 
  
 . 
  
 uniqid 
 (), 
  
 # Set the campaign ID to a temporary ID. 
  
 campaign 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 SMART_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 # The ad group type must be set to SMART_CAMPAIGN_ADS. 
  
 type 
  
 = 
>  
 SMART_CAMPAIGN_ADS 
  
 })})}); 
 } 
 # Creates a MutateOperation that creates a new ad group ad. 
 # A temporary ID will be used in the ad group resource name for this ad group ad 
 # to associate it with the ad group created in earlier steps. 
 sub 
  
 _create_ad_group_ad_operation 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 , 
  
 $ad_suggestions 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $mutate_operation 
  
 = 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 adGroupAdOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AdGroupAdService:: 
 AdGroupAdOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AdGroupAd 
 - 
> new 
 ({ 
  
 adGroup 
  
 = 
>  
 # Set the ad group ID to a temporary ID. 
  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 ad_group 
 ( 
  
 $customer_id 
 , 
  
 AD_GROUP_TEMPORARY_ID 
  
 ), 
  
 ad 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 Ad 
 - 
> new 
 ({ 
  
 # Set the type to SMART_CAMPAIGN_AD. 
  
 type 
  
 = 
>  
 SMART_CAMPAIGN_AD 
 , 
  
 smartCampaignAd 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 SmartCampaignAdInfo 
 - 
>  
 new 
 ({ 
  
 headlines 
  
 = 
>  
 [] 
 , 
  
 descriptions 
  
 = 
>  
 [] 
 })})})})}); 
  
 # The SmartCampaignAdInfo object includes headlines and descriptions 
  
 # retrieved from the SmartCampaignSuggestService.SuggestSmartCampaignAd 
  
 # method. It's recommended that users review and approve or update these 
  
 # creatives before they're set on the ad. It's possible that some or all of 
  
 # these assets may contain empty texts, which should not be set on the ad 
  
 # and instead should be replaced with meaningful texts from the user. Below 
  
 # we just accept the creatives that were suggested while filtering out empty 
  
 # assets. If no headlines or descriptions were suggested, then we manually 
  
 # add some, otherwise this operation will generate an INVALID_ARGUMENT 
  
 # error. Individual workflows will likely vary here. 
  
 my 
  
 $smart_campaign_ad 
  
 = 
  
 $mutate_operation 
 - 
> { 
 adGroupAdOperation 
 }{ 
 create 
 }{ 
 ad 
 }{ 
 smartCampaignAd 
 }; 
  
 foreach 
  
 my 
  
 $asset 
  
 ( 
 @ 
 { 
 $ad_suggestions 
 - 
> { 
 headlines 
 }}) 
  
 { 
  
 push 
  
 @ 
 { 
 $smart_campaign_ad 
 - 
> { 
 headlines 
 }}, 
  
 $asset 
  
 if 
  
 defined 
  
 $asset 
 - 
> { 
 text 
 }; 
  
 } 
  
 # If there are fewer headlines than are required, we manually add additional 
  
 # headlines to make up for the difference. 
  
 my 
  
 $num_missing_headlines 
  
 = 
  
 REQUIRED_NUM_HEADLINES 
  
 - 
  
 scalar 
  
 @ 
 { 
 $smart_campaign_ad 
 - 
> { 
 headlines 
 }}; 
  
 for 
  
 ( 
 my 
  
 $i 
  
 = 
  
 0 
  
 ; 
  
 $i 
 < 
 $num_missing_headlines 
  
 ; 
  
 $i 
 ++ 
 ) 
  
 { 
  
 push 
  
 @ 
 { 
 $smart_campaign_ad 
 - 
> { 
 headlines 
 }}, 
  
 Google::Ads::GoogleAds::V21::Common:: 
 AdTextAsset 
 - 
> new 
 ({ 
  
 text 
  
 = 
>  
 "placeholder headline " 
  
 . 
  
 $i 
  
 }); 
  
 } 
  
 foreach 
  
 my 
  
 $asset 
  
 ( 
 @ 
 { 
 $ad_suggestions 
 - 
> { 
 descriptions 
 }}) 
  
 { 
  
 push 
  
 @ 
 { 
 $smart_campaign_ad 
 - 
> { 
 descriptions 
 }}, 
  
 $asset 
  
 if 
  
 defined 
  
 $asset 
 - 
> { 
 text 
 }; 
  
 } 
  
 # If there are fewer descriptions than are required, we manually add 
  
 # additional descriptions to make up for the difference. 
  
 my 
  
 $num_missing_descriptions 
  
 = 
  
 REQUIRED_NUM_DESCRIPTIONS 
  
 - 
  
 scalar 
  
 @ 
 { 
 $smart_campaign_ad 
 - 
> { 
 descriptions 
 }}; 
  
 for 
  
 ( 
 my 
  
 $i 
  
 = 
  
 0 
  
 ; 
  
 $i 
 < 
 $num_missing_descriptions 
  
 ; 
  
 $i 
 ++ 
 ) 
  
 { 
  
 push 
  
 @ 
 { 
 $smart_campaign_ad 
 - 
> { 
 descriptions 
 }}, 
  
 Google::Ads::GoogleAds::V21::Common:: 
 AdTextAsset 
 - 
> new 
 ({ 
  
 text 
  
 = 
>  
 "placeholder description " 
  
 . 
  
 $i 
  
 }); 
  
 } 
  
 return 
  
 $mutate_operation 
 ; 
 } 
 # Prints the details of a MutateGoogleAdsResponse. 
 sub 
  
 _print_response_details 
  
 { 
  
 my 
  
 ( 
 $response 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $mutate_operation_responses 
  
 = 
  
 $response 
 - 
> { 
 mutateOperationResponses 
 }; 
  
 foreach 
  
 my 
  
 $operation_response 
  
 ( 
 @$mutate_operation_responses 
 ) 
  
 { 
  
 my 
  
 $resource_name 
  
 = 
  
 "<not found>" 
 ; 
  
 my 
  
 $entity_name 
  
 = 
  
 "unknown" 
 ; 
  
 if 
  
 ( 
 $operation_response 
 - 
> { 
 adGroupResult 
 }) 
  
 { 
  
 $entity_name 
  
 = 
  
 "AdGroup" 
 ; 
  
 $resource_name 
  
 = 
  
 $operation_response 
 - 
> { 
 adGroupResult 
 }{ 
 resourceName 
 }; 
  
 } 
  
 elsif 
  
 ( 
 $operation_response 
 - 
> { 
 adGroupAdResult 
 }) 
  
 { 
  
 $entity_name 
  
 = 
  
 "AdGroupAd" 
 ; 
  
 $resource_name 
  
 = 
  
 $operation_response 
 - 
> { 
 adGroupAdResult 
 }{ 
 resourceName 
 }; 
  
 } 
  
 elsif 
  
 ( 
 $operation_response 
 - 
> { 
 campaignResult 
 }) 
  
 { 
  
 $entity_name 
  
 = 
  
 "Campaign" 
 ; 
  
 $resource_name 
  
 = 
  
 $operation_response 
 - 
> { 
 campaignResult 
 }{ 
 resourceName 
 }; 
  
 } 
  
 elsif 
  
 ( 
 $operation_response 
 - 
> { 
 campaignBudgetResult 
 }) 
  
 { 
  
 $entity_name 
  
 = 
  
 "CampaignBudget" 
 ; 
  
 $resource_name 
  
 = 
  
 $operation_response 
 - 
> { 
 campaignBudgetResult 
 }{ 
 resourceName 
 }; 
  
 } 
  
 elsif 
  
 ( 
 $operation_response 
 - 
> { 
 campaignCriterionResult 
 }) 
  
 { 
  
 $entity_name 
  
 = 
  
 "CampaignCriterion" 
 ; 
  
 $resource_name 
  
 = 
  
 $operation_response 
 - 
> { 
 campaignCriterionResult 
 }{ 
 resourceName 
 }; 
  
 } 
  
 elsif 
  
 ( 
 $operation_response 
 - 
> { 
 smartCampaignSettingResult 
 }) 
  
 { 
  
 $entity_name 
  
 = 
  
 "SmartCampaignSetting" 
 ; 
  
 $resource_name 
  
 = 
  
 $operation_response 
 - 
> { 
 smartCampaignSettingResult 
 }{ 
 resourceName 
 }; 
  
 } 
  
 printf 
  
 "Created a(n) $entity_name with resource name '$resource_name'.\n" 
 ; 
  
 } 
 } 
 # Don't run the example if the file is being included. 
 if 
  
 ( 
 abs_path 
 ( 
 $0 
 ) 
  
 ne 
  
 abs_path 
 ( 
 __FILE__ 
 )) 
  
 { 
  
 return 
  
 1 
 ; 
 } 
 # Get Google Ads Client, credentials will be read from ~/googleads.properties. 
 my 
  
 $api_client 
  
 = 
  
 Google::Ads::GoogleAds:: 
 Client 
 - 
> new 
 (); 
 # By default examples are set to die on any server returned fault. 
 $api_client 
 - 
> set_die_on_faults 
 ( 
 1 
 ); 
 # Parameters passed on the command line will override any parameters set in code. 
 GetOptions 
 ( 
  
 "customer_id=s" 
  
 = 
>  
 \ 
 $customer_id 
 , 
  
 "keyword_text=s" 
  
 = 
>  
 \ 
 $keyword_text 
 , 
  
 "free_form_keyword_text=s" 
  
 = 
>  
 \ 
 $free_form_keyword_text 
 , 
  
 "business_profile_location=i" 
  
 = 
>  
 \ 
 $business_profile_location 
 , 
  
 "business_name=s" 
  
 = 
>  
 \ 
 $business_name 
 ); 
 # Print the help message if the parameters are not initialized in the code nor 
 # in the command line. 
 pod2usage 
 ( 
 2 
 ) 
  
 if 
  
 not 
  
 check_params 
 ( 
 $customer_id 
 ); 
 # Call the example. 
 add_smart_campaign 
 ( 
 $api_client 
 , 
  
 $customer_id 
  
 =~ 
  
 s/-//g 
 r 
 , 
  
 $keyword_text 
 , 
  
 $free_form_keyword_text 
 , 
  
 $business_profile_location 
 , 
  
 $business_name 
 ); 
 =pod 
 =head1 NAME 
 add_smart_campaign 
 =head1 DESCRIPTION 
 This example shows how to create a Smart campaign. 
 More details on Smart campaigns can be found here: 
 https://support.google.com/google-ads/answer/7652860 
 =head1 SYNOPSIS 
 add_smart_campaign.pl [options] 
 -help                       Show the help message. 
 -customer_id                The Google Ads customer ID. 
 -keyword_text               [optional] A keyword text used to retrieve keyword theme constant 
 suggestions from the KeywordThemeConstantService. These keyword 
 theme suggestions are generated using auto-completion data for the 
 given text and may help improve the performance of the Smart campaign. 
 -free_form_keyword_text      [optional] A keyword text used to create a free-form keyword theme, 
 which is entirely user-specified and not derived from any suggestion 
 service. Using free-form keyword themes is typically not recommended 
 because they are less effective than suggested keyword themes, however 
 they are useful in situations where a very specific term needs to be targeted. 
 -business_profile_location  [optional] The resource name of a Business Profile location. 
 This is required if a business name is not provided. 
 This ID can be retrieved using the Business Profile API, for details see: 
 https://developers.google.com/my-business/reference/businessinformation/rest/v1/accounts.locations 
 or from the Business Profile UI (https://support.google.com/business/answer/10737668). 
 -business_name              [optional] The name of a business in Business Profile. 
 This is required if a business profile location is not provided. 
 =cut 
  
  
Create a Mobile Website
View Site in Mobile | Classic
Share by: