Add Performance Max 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 
 // 
 //     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. 
 package 
  
 com.google.ads.googleads.examples.advancedoperations 
 ; 
 import static 
  
 com.google.ads.googleads.examples.utils.CodeSampleHelper.getPrintableDateTime 
 ; 
 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.CodeSampleParams 
 ; 
 import 
  
 com.google.ads.googleads.lib.GoogleAdsClient 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.AudienceInfo 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.ImageAsset 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.LanguageInfo 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.LocationInfo 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.MaximizeConversionValue 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.SearchThemeInfo 
 ; 
 import 
  
 com.google.ads.googleads.v21.common.TextAsset 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.AdvertisingChannelTypeEnum.AdvertisingChannelType 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.AssetFieldTypeEnum.AssetFieldType 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.AssetGroupStatusEnum.AssetGroupStatus 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.BudgetDeliveryMethodEnum.BudgetDeliveryMethod 
 ; 
 import 
  
 com.google.ads.googleads.v21.enums.CampaignStatusEnum.CampaignStatus 
 ; 
 import 
  
 com.google.ads.googleads.v21.errors.GoogleAdsError 
 ; 
 import 
  
 com.google.ads.googleads.v21.errors.GoogleAdsException 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.Asset 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.AssetGroup 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.AssetGroupAsset 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.AssetGroupSignal 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.Campaign 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.CampaignAsset 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.CampaignBudget 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.CampaignCriterion 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.AssetGroupAssetOperation 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.AssetGroupOperation 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.AssetGroupSignalOperation 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.AssetOperation 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.CampaignAssetOperation 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.CampaignBudgetOperation 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.CampaignCriterionOperation 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.CampaignOperation 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.GoogleAdsServiceClient 
 ; 
 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.utils.ResourceNames 
 ; 
 import 
  
 com.google.common.collect.ImmutableList 
 ; 
 import 
  
 com.google.common.io.ByteStreams 
 ; 
 import 
  
 com.google.protobuf.ByteString 
 ; 
 import 
  
 com.google.protobuf.Descriptors.FieldDescriptor 
 ; 
 import 
  
 java.io.FileNotFoundException 
 ; 
 import 
  
 java.io.IOException 
 ; 
 import 
  
 java.net.URL 
 ; 
 import 
  
 java.util.ArrayList 
 ; 
 import 
  
 java.util.List 
 ; 
 import 
  
 java.util.Map.Entry 
 ; 
 import 
  
 java.util.stream.Collectors 
 ; 
 import 
  
 org.joda.time.DateTime 
 ; 
 /** 
 * This example shows how to create a Performance Max campaign. 
 * 
 * <p>For more information about Performance Max campaigns, see 
 * https://developers.google.com/google-ads/api/docs/performance-max/overview 
 * 
 * <p>Prerequisites: - You must have at least one conversion action in the account. For more about 
 * conversion actions, see 
 * https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions 
 * 
 * <p>This example uses the default customer conversion goals. For an example of setting 
 * campaign-specific conversion goals, see {@link 
 * com.google.ads.googleads.examples.shoppingads.AddPerformanceMaxRetailCampaign}. 
 */ 
 public 
  
 class 
 AddPerformanceMaxCampaign 
  
 { 
  
 // We specify temporary IDs that are specific to a single mutate request. Temporary IDs are always 
  
 // negative and unique within one mutate request. 
  
 // 
  
 // <p>See https://developers.google.com/google-ads/api/docs/mutating/best-practices for further 
  
 // details. 
  
 // 
  
 // <p>These temporary IDs are fixed because they are used in multiple places. 
  
 private 
  
 static 
  
 final 
  
 int 
  
 BUDGET_TEMPORARY_ID 
  
 = 
  
 - 
 1 
 ; 
  
 private 
  
 static 
  
 final 
  
 int 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 = 
  
 - 
 2 
 ; 
  
 private 
  
 static 
  
 final 
  
 int 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 = 
  
 - 
 3 
 ; 
  
 // There are also entities that will be created in the same request but do not 
  
 // need to be fixed temporary IDs because they are referenced only once. 
  
 private 
  
 static 
  
 long 
  
 temporaryId 
  
 = 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 - 
  
 1 
 ; 
  
 private 
  
 static 
  
 class 
 AddPerformanceMaxCampaignParams 
  
 extends 
  
 CodeSampleParams 
  
 { 
  
 @Parameter 
 ( 
 names 
  
 = 
  
 ArgumentNames 
 . 
 CUSTOMER_ID 
 , 
  
 required 
  
 = 
  
 true 
 ) 
  
 private 
  
 Long 
  
 customerId 
 ; 
  
 @Parameter 
 ( 
  
 names 
  
 = 
  
 ArgumentNames 
 . 
 AUDIENCE_ID 
 , 
  
 description 
  
 = 
  
 "An audience ID to use to improve the targeting of the Performance Max campaign" 
 ) 
  
 private 
  
 Long 
  
 audienceId 
 ; 
  
 @Parameter 
 ( 
  
 names 
  
 = 
  
 "--brandGuidelinesEnabled" 
 , 
  
 arity 
  
 = 
  
 1 
 , 
  
 description 
  
 = 
  
 "A boolean value indicating if the created campaign is enabled for brand guidelines" 
 ) 
  
 private 
  
 boolean 
  
 brandGuidelinesEnabled 
  
 = 
  
 false 
 ; 
  
 } 
  
 public 
  
 static 
  
 void 
  
 main 
 ( 
 String 
 [] 
  
 args 
 ) 
  
 throws 
  
 IOException 
  
 { 
  
 AddPerformanceMaxCampaignParams 
  
 params 
  
 = 
  
 new 
  
 AddPerformanceMaxCampaignParams 
 (); 
  
 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" 
 ); 
  
 // Optional: Specify an audience ID. 
  
 // params.audienceId = Long.parseLong("INSERT_AUDIENCE_ID_HERE"); 
  
 } 
  
 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 
  
 AddPerformanceMaxCampaign 
 () 
  
 . 
 runExample 
 ( 
  
 googleAdsClient 
 , 
  
 params 
 . 
 customerId 
 , 
  
 params 
 . 
 audienceId 
 , 
  
 params 
 . 
 brandGuidelinesEnabled 
 ); 
  
 } 
  
 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 
 ); 
  
 } 
  
 } 
  
 /** 
 * Runs the example. 
 * 
 * @param googleAdsClient the Google Ads API client. 
 * @param customerId the client customer ID. 
 * @param audienceId the optional audience ID. 
 * @param brandGuidelinesEnabled indicates if the campaign is enabled for brand guidelines. 
 */ 
  
 private 
  
 void 
  
 runExample 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long 
  
 customerId 
 , 
  
 Long 
  
 audienceId 
 , 
  
 boolean 
  
 brandGuidelinesEnabled 
 ) 
  
 throws 
  
 IOException 
  
 { 
  
 // Performance Max campaigns require that repeated assets such as headlines 
  
 // and descriptions be created before the campaign. 
  
 // For the list of required assets for a Performance Max campaign, see 
  
 // https://developers.google.com/google-ads/api/docs/performance-max/assets 
  
 // 
  
 // Creates the headlines. 
  
 List<String> 
  
 headlines 
  
 = 
  
 ImmutableList 
 . 
 of 
 ( 
 "Travel" 
 , 
  
 "Travel Reviews" 
 , 
  
 "Book travel" 
 ); 
  
 List<String> 
  
 headlineAssetResourceNames 
  
 = 
  
 createMultipleTextAssets 
 ( 
 googleAdsClient 
 , 
  
 customerId 
 , 
  
 headlines 
 ); 
  
 // Creates the descriptions. 
  
 List<String> 
  
 descriptions 
  
 = 
  
 ImmutableList 
 . 
 of 
 ( 
 "Take to the air!" 
 , 
  
 "Fly to the sky!" 
 ); 
  
 List<String> 
  
 descriptionAssetResourceNames 
  
 = 
  
 createMultipleTextAssets 
 ( 
 googleAdsClient 
 , 
  
 customerId 
 , 
  
 descriptions 
 ); 
  
 // 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 Performance Max 
  
 // 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 
  
 List<MutateOperation> 
  
 mutateOperations 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 mutateOperations 
 . 
 add 
 ( 
 createCampaignBudgetOperation 
 ( 
 customerId 
 )); 
  
 mutateOperations 
 . 
 add 
 ( 
 createPerformanceMaxCampaignOperation 
 ( 
 customerId 
 , 
  
 brandGuidelinesEnabled 
 )); 
  
 mutateOperations 
 . 
 addAll 
 ( 
 createCampaignCriterionOperations 
 ( 
 customerId 
 )); 
  
 String 
  
 assetGroupResourceName 
  
 = 
  
 ResourceNames 
 . 
 assetGroup 
 ( 
 customerId 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 ); 
  
 mutateOperations 
 . 
 addAll 
 ( 
  
 createAssetGroupOperations 
 ( 
  
 customerId 
 , 
  
 assetGroupResourceName 
 , 
  
 headlineAssetResourceNames 
 , 
  
 descriptionAssetResourceNames 
 , 
  
 brandGuidelinesEnabled 
 )); 
  
 mutateOperations 
 . 
 addAll 
 ( 
  
 createAssetGroupSignalOperations 
 ( 
 customerId 
 , 
  
 assetGroupResourceName 
 , 
  
 audienceId 
 )); 
  
 try 
  
 ( 
 GoogleAdsServiceClient 
  
 googleAdsServiceClient 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createGoogleAdsServiceClient 
 ()) 
  
 { 
  
 MutateGoogleAdsResponse 
  
 response 
  
 = 
  
 googleAdsServiceClient 
 . 
 mutate 
 ( 
 Long 
 . 
 toString 
 ( 
 customerId 
 ), 
  
 mutateOperations 
 ); 
  
 printResponseDetails 
 ( 
 response 
 ); 
  
 } 
  
 } 
  
 /** Creates a MutateOperation that creates a new CampaignBudget. */ 
  
 private 
  
 MutateOperation 
  
 createCampaignBudgetOperation 
 ( 
 long 
  
 customerId 
 ) 
  
 { 
  
 CampaignBudget 
  
 campaignBudget 
  
 = 
  
 CampaignBudget 
 . 
 newBuilder 
 () 
  
 . 
 setName 
 ( 
 "Performance Max campaign budget #" 
  
 + 
  
 getPrintableDateTime 
 ()) 
  
 // The budget period already defaults to DAILY. 
  
 . 
 setAmountMicros 
 ( 
 50_000_000 
 ) 
  
 . 
 setDeliveryMethod 
 ( 
 BudgetDeliveryMethod 
 . 
 STANDARD 
 ) 
  
 // A Performance Max campaign cannot use a shared campaign budget. 
  
 . 
 setExplicitlyShared 
 ( 
 false 
 ) 
  
 // Set 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 
 )) 
  
 . 
 build 
 (); 
  
 return 
  
 MutateOperation 
 . 
 newBuilder 
 () 
  
 . 
 setCampaignBudgetOperation 
 ( 
  
 CampaignBudgetOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 campaignBudget 
 ). 
 build 
 ()) 
  
 . 
 build 
 (); 
  
 } 
  
 /** Creates a MutateOperation that creates a new Performance Max campaign. */ 
  
 private 
  
 MutateOperation 
  
 createPerformanceMaxCampaignOperation 
 ( 
  
 long 
  
 customerId 
 , 
  
 boolean 
  
 brandGuidelinesEnabled 
 ) 
  
 { 
  
 Campaign 
  
 performanceMaxCampaign 
  
 = 
  
 Campaign 
 . 
 newBuilder 
 () 
  
 . 
 setName 
 ( 
 "Performance Max campaign #" 
  
 + 
  
 getPrintableDateTime 
 ()) 
  
 // Sets the campaign status as PAUSED. The campaign is the only entity in 
  
 // the mutate request that should have its status set. 
  
 . 
 setStatus 
 ( 
 CampaignStatus 
 . 
 PAUSED 
 ) 
  
 // All Performance Max campaigns have an advertising_channel_type of 
  
 // PERFORMANCE_MAX. The advertising_channel_sub_type should not be set. 
  
 . 
 setAdvertisingChannelType 
 ( 
 AdvertisingChannelType 
 . 
 PERFORMANCE_MAX 
 ) 
  
 // Bidding strategy must be set directly on the campaign. 
  
 // Setting a portfolio bidding strategy by resource name is not supported. 
  
 // Max Conversion and Maximize Conversion Value are the only strategies 
  
 // supported for Performance Max campaigns. 
  
 // An optional ROAS (Return on Advertising Spend) can be set for 
  
 // maximize_conversion_value. The ROAS value must be specified as a ratio in 
  
 // the API. It is calculated by dividing "total value" by "total spend". 
  
 // For more information on Maximize Conversion Value, see the support 
  
 // article: http://support.google.com/google-ads/answer/7684216. 
  
 // A targetRoas of 3.5 corresponds to a 350% return on ad spend. 
  
 . 
 setMaximizeConversionValue 
 ( 
  
 MaximizeConversionValue 
 . 
 newBuilder 
 (). 
 setTargetRoas 
 ( 
 3.5 
 ). 
 build 
 ()) 
  
 // Sets the Final URL expansion opt out. This flag is specific to 
  
 // Performance Max campaigns. If opted out (True), only the final URLs in 
  
 // the asset group or URLs specified in the advertiser's Google Merchant 
  
 // Center or business data feeds are targeted. 
  
 // If opted in (False), the entire domain will be targeted. For best 
  
 // results, set this value to false to opt in and allow URL expansions. You 
  
 // can optionally add exclusions to limit traffic to parts of your website. 
  
 . 
 setUrlExpansionOptOut 
 ( 
 false 
 ) 
  
 // Sets if the campaign is enabled for brand guidelines. For more information on brand 
  
 // guidelines, see https://support.google.com/google-ads/answer/14934472. 
  
 . 
 setBrandGuidelinesEnabled 
 ( 
 brandGuidelinesEnabled 
 ) 
  
 // Assigns the resource name with a temporary ID. 
  
 . 
 setResourceName 
 ( 
  
 ResourceNames 
 . 
 campaign 
 ( 
 customerId 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 )) 
  
 // Sets the budget using the given budget resource name. 
  
 . 
 setCampaignBudget 
 ( 
 ResourceNames 
 . 
 campaignBudget 
 ( 
 customerId 
 , 
  
 BUDGET_TEMPORARY_ID 
 )) 
  
 // Declares whether this campaign serves political ads targeting the EU. 
  
 . 
 setContainsEuPoliticalAdvertising 
 ( 
 DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING 
 ) 
  
 // Optional fields. 
  
 . 
 setStartDate 
 ( 
 new 
  
 DateTime 
 (). 
 plusDays 
 ( 
 1 
 ). 
 toString 
 ( 
 "yyyyMMdd" 
 )) 
  
 . 
 setEndDate 
 ( 
 new 
  
 DateTime 
 (). 
 plusDays 
 ( 
 365 
 ). 
 toString 
 ( 
 "yyyyMMdd" 
 )) 
  
 . 
 build 
 (); 
  
 return 
  
 MutateOperation 
 . 
 newBuilder 
 () 
  
 . 
 setCampaignOperation 
 ( 
  
 CampaignOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 performanceMaxCampaign 
 ). 
 build 
 ()) 
  
 . 
 build 
 (); 
  
 } 
  
 /** Creates a list of MutateOperations that create new campaign criteria. */ 
  
 private 
  
 List<MutateOperation> 
  
 createCampaignCriterionOperations 
 ( 
 long 
  
 customerId 
 ) 
  
 { 
  
 String 
  
 campaignResourceName 
  
 = 
  
 ResourceNames 
 . 
 campaign 
 ( 
 customerId 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ); 
  
 List<CampaignCriterion> 
  
 campaignCriteria 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 // Sets the LOCATION campaign criteria. 
  
 // Targets all of New York City except Brooklyn. 
  
 // Location IDs are listed here: 
  
 // https://developers.google.com/google-ads/api/reference/data/geotargets 
  
 // and they can also be retrieved using the GeoTargetConstantService as shown 
  
 // here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting 
  
 // 
  
 // We will add one positive location target for New York City (ID=1023191) 
  
 // and one negative location target for Brooklyn (ID=1022762). 
  
 // First, adds the positive (negative = False) for New York City. 
  
 campaignCriteria 
 . 
 add 
 ( 
  
 CampaignCriterion 
 . 
 newBuilder 
 () 
  
 . 
 setCampaign 
 ( 
 campaignResourceName 
 ) 
  
 . 
 setLocation 
 ( 
  
 LocationInfo 
 . 
 newBuilder 
 () 
  
 . 
 setGeoTargetConstant 
 ( 
 ResourceNames 
 . 
 geoTargetConstant 
 ( 
 1023191 
 )) 
  
 . 
 build 
 ()) 
  
 . 
 setNegative 
 ( 
 false 
 ) 
  
 . 
 build 
 ()); 
  
 // Next adds the negative target for Brooklyn. 
  
 campaignCriteria 
 . 
 add 
 ( 
  
 CampaignCriterion 
 . 
 newBuilder 
 () 
  
 . 
 setCampaign 
 ( 
 campaignResourceName 
 ) 
  
 . 
 setLocation 
 ( 
  
 LocationInfo 
 . 
 newBuilder 
 () 
  
 . 
 setGeoTargetConstant 
 ( 
 ResourceNames 
 . 
 geoTargetConstant 
 ( 
 1022762 
 )) 
  
 . 
 build 
 ()) 
  
 . 
 setNegative 
 ( 
 true 
 ) 
  
 . 
 build 
 ()); 
  
 // Sets the LANGUAGE campaign criterion. 
  
 campaignCriteria 
 . 
 add 
 ( 
  
 CampaignCriterion 
 . 
 newBuilder 
 () 
  
 . 
 setCampaign 
 ( 
 campaignResourceName 
 ) 
  
 // Sets the language. 
  
 // For a list of all language codes, see: 
  
 // https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 
  
 . 
 setLanguage 
 ( 
  
 LanguageInfo 
 . 
 newBuilder 
 () 
  
 . 
 setLanguageConstant 
 ( 
 ResourceNames 
 . 
 languageConstant 
 ( 
 1000 
 )) 
  
 // English 
  
 . 
 build 
 ()) 
  
 . 
 build 
 ()); 
  
 // Returns a list of mutate operations with one operation per criterion. 
  
 return 
  
 campaignCriteria 
 . 
 stream 
 () 
  
 . 
 map 
 ( 
  
 criterion 
  
 - 
>  
 MutateOperation 
 . 
 newBuilder 
 () 
  
 . 
 setCampaignCriterionOperation 
 ( 
  
 CampaignCriterionOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 criterion 
 ). 
 build 
 ()) 
  
 . 
 build 
 ()) 
  
 . 
 collect 
 ( 
 Collectors 
 . 
 toList 
 ()); 
  
 } 
  
 /** Creates multiple text assets and returns the list of resource names. */ 
  
 private 
  
 List<String> 
  
 createMultipleTextAssets 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long 
  
 customerId 
 , 
  
 List<String> 
  
 texts 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 mutateOperations 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 for 
  
 ( 
 String 
  
 text 
  
 : 
  
 texts 
 ) 
  
 { 
  
 Asset 
  
 asset 
  
 = 
  
 Asset 
 . 
 newBuilder 
 (). 
 setTextAsset 
 ( 
 TextAsset 
 . 
 newBuilder 
 (). 
 setText 
 ( 
 text 
 )). 
 build 
 (); 
  
 AssetOperation 
  
 assetOperation 
  
 = 
  
 AssetOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 asset 
 ). 
 build 
 (); 
  
 mutateOperations 
 . 
 add 
 ( 
 MutateOperation 
 . 
 newBuilder 
 (). 
 setAssetOperation 
 ( 
 assetOperation 
 ). 
 build 
 ()); 
  
 } 
  
 List<String> 
  
 assetResourceNames 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 // Creates the service client. 
  
 try 
  
 ( 
 GoogleAdsServiceClient 
  
 googleAdsServiceClient 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createGoogleAdsServiceClient 
 ()) 
  
 { 
  
 // Sends the operations in a single Mutate request. 
  
 MutateGoogleAdsResponse 
  
 response 
  
 = 
  
 googleAdsServiceClient 
 . 
 mutate 
 ( 
 Long 
 . 
 toString 
 ( 
 customerId 
 ), 
  
 mutateOperations 
 ); 
  
 for 
  
 ( 
 MutateOperationResponse 
  
 result 
  
 : 
  
 response 
 . 
 getMutateOperationResponsesList 
 ()) 
  
 { 
  
 if 
  
 ( 
 result 
 . 
 hasAssetResult 
 ()) 
  
 { 
  
 assetResourceNames 
 . 
 add 
 ( 
 result 
 . 
 getAssetResult 
 (). 
 getResourceName 
 ()); 
  
 } 
  
 } 
  
 printResponseDetails 
 ( 
 response 
 ); 
  
 } 
  
 return 
  
 assetResourceNames 
 ; 
  
 } 
  
 /** Creates a list of MutateOperations that create a new AssetGroup. */ 
  
 private 
  
 List<MutateOperation> 
  
 createAssetGroupOperations 
 ( 
  
 long 
  
 customerId 
 , 
  
 String 
  
 assetGroupResourceName 
 , 
  
 List<String> 
  
 headlineAssetResourceNames 
 , 
  
 List<String> 
  
 descriptionAssetResourceNames 
 , 
  
 boolean 
  
 brandGuidelinesEnabled 
 ) 
  
 throws 
  
 IOException 
  
 { 
  
 List<MutateOperation> 
  
 mutateOperations 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 String 
  
 campaignResourceName 
  
 = 
  
 ResourceNames 
 . 
 campaign 
 ( 
 customerId 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ); 
  
 // Creates the AssetGroup. 
  
 AssetGroup 
  
 assetGroup 
  
 = 
  
 AssetGroup 
 . 
 newBuilder 
 () 
  
 . 
 setName 
 ( 
 "Performance Max asset group #" 
  
 + 
  
 getPrintableDateTime 
 ()) 
  
 . 
 setCampaign 
 ( 
 campaignResourceName 
 ) 
  
 . 
 addFinalUrls 
 ( 
 "http://www.example.com" 
 ) 
  
 . 
 addFinalMobileUrls 
 ( 
 "http://www.example.com" 
 ) 
  
 . 
 setStatus 
 ( 
 AssetGroupStatus 
 . 
 PAUSED 
 ) 
  
 . 
 setResourceName 
 ( 
 assetGroupResourceName 
 ) 
  
 . 
 build 
 (); 
  
 AssetGroupOperation 
  
 assetGroupOperation 
  
 = 
  
 AssetGroupOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 assetGroup 
 ). 
 build 
 (); 
  
 mutateOperations 
 . 
 add 
 ( 
  
 MutateOperation 
 . 
 newBuilder 
 (). 
 setAssetGroupOperation 
 ( 
 assetGroupOperation 
 ). 
 build 
 ()); 
  
 // For the list of required assets for a Performance Max campaign, see 
  
 // https://developers.google.com/google-ads/api/docs/performance-max/assets 
  
 // An AssetGroup is linked to an Asset by creating a new AssetGroupAsset 
  
 // and providing: 
  
 //   the resource name of the AssetGroup 
  
 //   the resource name of the Asset 
  
 //   the field_type of the Asset in this AssetGroup. 
  
 // To learn more about AssetGroups, see 
  
 // https://developers.google.com/google-ads/api/docs/performance-max/asset-groups 
  
 // Links the previously created multiple text assets. 
  
 // Links the headline assets. 
  
 for 
  
 ( 
 String 
  
 resourceName 
  
 : 
  
 headlineAssetResourceNames 
 ) 
  
 { 
  
 mutateOperations 
 . 
 add 
 ( 
  
 createAssetGroupAssetMutateOperation 
 ( 
  
 AssetFieldType 
 . 
 HEADLINE 
 , 
  
 resourceName 
 , 
  
 assetGroupResourceName 
 )); 
  
 } 
  
 // Links the description assets. 
  
 for 
  
 ( 
 String 
  
 resourceName 
  
 : 
  
 descriptionAssetResourceNames 
 ) 
  
 { 
  
 mutateOperations 
 . 
 add 
 ( 
  
 createAssetGroupAssetMutateOperation 
 ( 
  
 AssetFieldType 
 . 
 DESCRIPTION 
 , 
  
 resourceName 
 , 
  
 assetGroupResourceName 
 )); 
  
 } 
  
 // Creates and links the long headline text asset. 
  
 List<MutateOperation> 
  
 createAndLinkTextAssetOperations 
  
 = 
  
 createAndLinkTextAsset 
 ( 
 customerId 
 , 
  
 "Travel the World" 
 , 
  
 AssetFieldType 
 . 
 LONG_HEADLINE 
 ); 
  
 mutateOperations 
 . 
 addAll 
 ( 
 createAndLinkTextAssetOperations 
 ); 
  
 // Creates and links the business name and logo assets. 
  
 List<MutateOperation> 
  
 createAndLinkBrandAssets 
  
 = 
  
 createAndLinkBrandAssets 
 ( 
  
 customerId 
 , 
  
 brandGuidelinesEnabled 
 , 
  
 "Interplanetary Cruises" 
 , 
  
 "https://gaagl.page.link/bjYi" 
 , 
  
 "Marketing Logo" 
 ); 
  
 mutateOperations 
 . 
 addAll 
 ( 
 createAndLinkBrandAssets 
 ); 
  
 // Creates and links the image assets. 
  
 // Creates and links the Marketing Image Asset. 
  
 createAndLinkTextAssetOperations 
  
 = 
  
 createAndLinkImageAsset 
 ( 
  
 customerId 
 , 
  
 "https://gaagl.page.link/Eit5" 
 , 
  
 AssetFieldType 
 . 
 MARKETING_IMAGE 
 , 
  
 "Marketing Image" 
 ); 
  
 mutateOperations 
 . 
 addAll 
 ( 
 createAndLinkTextAssetOperations 
 ); 
  
 // Creates and links the Square Marketing Image Asset. 
  
 createAndLinkTextAssetOperations 
  
 = 
  
 createAndLinkImageAsset 
 ( 
  
 customerId 
 , 
  
 "https://gaagl.page.link/bjYi" 
 , 
  
 AssetFieldType 
 . 
 SQUARE_MARKETING_IMAGE 
 , 
  
 "Square Marketing Image" 
 ); 
  
 mutateOperations 
 . 
 addAll 
 ( 
 createAndLinkTextAssetOperations 
 ); 
  
 return 
  
 mutateOperations 
 ; 
  
 } 
  
 /** Creates a list of MutateOperations that create a new linked text asset. */ 
  
 List<MutateOperation> 
  
 createAndLinkTextAsset 
 ( 
  
 long 
  
 customerId 
 , 
  
 String 
  
 text 
 , 
  
 AssetFieldType 
  
 assetFieldType 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 mutateOperations 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 String 
  
 assetResourceName 
  
 = 
  
 ResourceNames 
 . 
 asset 
 ( 
 customerId 
 , 
  
 getNextTemporaryId 
 ()); 
  
 // Creates the Text Asset. 
  
 Asset 
  
 asset 
  
 = 
  
 Asset 
 . 
 newBuilder 
 () 
  
 . 
 setResourceName 
 ( 
 assetResourceName 
 ) 
  
 . 
 setTextAsset 
 ( 
 TextAsset 
 . 
 newBuilder 
 (). 
 setText 
 ( 
 text 
 ). 
 build 
 ()) 
  
 . 
 build 
 (); 
  
 AssetOperation 
  
 assetOperation 
  
 = 
  
 AssetOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 asset 
 ). 
 build 
 (); 
  
 mutateOperations 
 . 
 add 
 ( 
 MutateOperation 
 . 
 newBuilder 
 (). 
 setAssetOperation 
 ( 
 assetOperation 
 ). 
 build 
 ()); 
  
 // Creates an AssetGroupAsset to link the Asset to the AssetGroup. 
  
 mutateOperations 
 . 
 add 
 ( 
  
 createAssetGroupAssetMutateOperation 
 ( 
  
 assetFieldType 
 , 
  
 assetResourceName 
 , 
  
 ResourceNames 
 . 
 assetGroup 
 ( 
 customerId 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 ))); 
  
 return 
  
 mutateOperations 
 ; 
  
 } 
  
 /** Creates a list of MutateOperations that create a new linked image asset. */ 
  
 List<MutateOperation> 
  
 createAndLinkImageAsset 
 ( 
  
 long 
  
 customerId 
 , 
  
 String 
  
 url 
 , 
  
 AssetFieldType 
  
 assetFieldType 
 , 
  
 String 
  
 assetName 
 ) 
  
 throws 
  
 IOException 
  
 { 
  
 List<MutateOperation> 
  
 mutateOperations 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 String 
  
 assetResourceName 
  
 = 
  
 ResourceNames 
 . 
 asset 
 ( 
 customerId 
 , 
  
 getNextTemporaryId 
 ()); 
  
 // Creates a media file. 
  
 byte 
 [] 
  
 assetBytes 
  
 = 
  
 ByteStreams 
 . 
 toByteArray 
 ( 
 new 
  
 URL 
 ( 
 url 
 ). 
 openStream 
 ()); 
  
 // Creates the Image Asset. 
  
 Asset 
  
 asset 
  
 = 
  
 Asset 
 . 
 newBuilder 
 () 
  
 . 
 setResourceName 
 ( 
 assetResourceName 
 ) 
  
 . 
 setImageAsset 
 ( 
 ImageAsset 
 . 
 newBuilder 
 (). 
 setData 
 ( 
 ByteString 
 . 
 copyFrom 
 ( 
 assetBytes 
 )). 
 build 
 ()) 
  
 // Provides a unique friendly name to identify your asset. When there is an existing 
  
 // image asset with the same content but a different name, the new name will be dropped 
  
 // silently. 
  
 . 
 setName 
 ( 
 assetName 
 ) 
  
 . 
 build 
 (); 
  
 AssetOperation 
  
 assetOperation 
  
 = 
  
 AssetOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 asset 
 ). 
 build 
 (); 
  
 mutateOperations 
 . 
 add 
 ( 
 MutateOperation 
 . 
 newBuilder 
 (). 
 setAssetOperation 
 ( 
 assetOperation 
 ). 
 build 
 ()); 
  
 // Creates an AssetGroupAsset to link the Asset to the AssetGroup. 
  
 mutateOperations 
 . 
 add 
 ( 
  
 createAssetGroupAssetMutateOperation 
 ( 
  
 assetFieldType 
 , 
  
 assetResourceName 
 , 
  
 ResourceNames 
 . 
 assetGroup 
 ( 
 customerId 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 ))); 
  
 return 
  
 mutateOperations 
 ; 
  
 } 
  
 /** Creates a list of MutateOperations that create linked brand assets. */ 
  
 List<MutateOperation> 
  
 createAndLinkBrandAssets 
 ( 
  
 long 
  
 customerId 
 , 
  
 boolean 
  
 brandGuidelinesEnabled 
 , 
  
 String 
  
 businessName 
 , 
  
 String 
  
 logoUrl 
 , 
  
 String 
  
 logoName 
 ) 
  
 throws 
  
 IOException 
  
 { 
  
 List<MutateOperation> 
  
 mutateOperations 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 // Creates the brand name text asset. 
  
 String 
  
 businessNameAssetResourceName 
  
 = 
  
 ResourceNames 
 . 
 asset 
 ( 
 customerId 
 , 
  
 getNextTemporaryId 
 ()); 
  
 Asset 
  
 businessNameAsset 
  
 = 
  
 Asset 
 . 
 newBuilder 
 () 
  
 . 
 setResourceName 
 ( 
 businessNameAssetResourceName 
 ) 
  
 . 
 setTextAsset 
 ( 
 TextAsset 
 . 
 newBuilder 
 (). 
 setText 
 ( 
 businessName 
 ). 
 build 
 ()) 
  
 . 
 build 
 (); 
  
 AssetOperation 
  
 businessNameAssetOperation 
  
 = 
  
 AssetOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 businessNameAsset 
 ). 
 build 
 (); 
  
 mutateOperations 
 . 
 add 
 ( 
  
 MutateOperation 
 . 
 newBuilder 
 (). 
 setAssetOperation 
 ( 
 businessNameAssetOperation 
 ). 
 build 
 ()); 
  
 // Creates the logo image asset. 
  
 String 
  
 logoAssetResourceName 
  
 = 
  
 ResourceNames 
 . 
 asset 
 ( 
 customerId 
 , 
  
 getNextTemporaryId 
 ()); 
  
 // Creates a media file. 
  
 byte 
 [] 
  
 logoBytes 
  
 = 
  
 ByteStreams 
 . 
 toByteArray 
 ( 
 new 
  
 URL 
 ( 
 logoUrl 
 ). 
 openStream 
 ()); 
  
 Asset 
  
 logoAsset 
  
 = 
  
 Asset 
 . 
 newBuilder 
 () 
  
 . 
 setResourceName 
 ( 
 logoAssetResourceName 
 ) 
  
 . 
 setImageAsset 
 ( 
 ImageAsset 
 . 
 newBuilder 
 (). 
 setData 
 ( 
 ByteString 
 . 
 copyFrom 
 ( 
 logoBytes 
 )). 
 build 
 ()) 
  
 // Provides a unique friendly name to identify your asset. When there is an existing 
  
 // image asset with the same content but a different name, the new name will be dropped 
  
 // silently. 
  
 . 
 setName 
 ( 
 logoName 
 ) 
  
 . 
 build 
 (); 
  
 AssetOperation 
  
 logoImageAssetOperation 
  
 = 
  
 AssetOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 logoAsset 
 ). 
 build 
 (); 
  
 mutateOperations 
 . 
 add 
 ( 
  
 MutateOperation 
 . 
 newBuilder 
 (). 
 setAssetOperation 
 ( 
 logoImageAssetOperation 
 ). 
 build 
 ()); 
  
 if 
  
 ( 
 brandGuidelinesEnabled 
 ) 
  
 { 
  
 // Creates CampaignAsset resources to link the Asset resources to the Campaign. 
  
 mutateOperations 
 . 
 add 
 ( 
  
 createCampaignAssetMutateOperation 
 ( 
  
 customerId 
 , 
  
 AssetFieldType 
 . 
 BUSINESS_NAME 
 , 
  
 businessNameAssetResourceName 
 )); 
  
 mutateOperations 
 . 
 add 
 ( 
  
 createCampaignAssetMutateOperation 
 ( 
  
 customerId 
 , 
  
 AssetFieldType 
 . 
 LOGO 
 , 
  
 logoAssetResourceName 
 )); 
  
 } 
  
 else 
  
 { 
  
 // Creates an AssetGroupAsset to link the Asset to the AssetGroup. 
  
 mutateOperations 
 . 
 add 
 ( 
  
 createAssetGroupAssetMutateOperation 
 ( 
  
 AssetFieldType 
 . 
 BUSINESS_NAME 
 , 
  
 businessNameAssetResourceName 
 , 
  
 ResourceNames 
 . 
 assetGroup 
 ( 
 customerId 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 ))); 
  
 mutateOperations 
 . 
 add 
 ( 
  
 createAssetGroupAssetMutateOperation 
 ( 
  
 AssetFieldType 
 . 
 LOGO 
 , 
  
 logoAssetResourceName 
 , 
  
 ResourceNames 
 . 
 assetGroup 
 ( 
 customerId 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 ))); 
  
 } 
  
 return 
  
 mutateOperations 
 ; 
  
 } 
  
 /** Creates a MutateOperation to add an AssetGroupAsset. */ 
  
 MutateOperation 
  
 createAssetGroupAssetMutateOperation 
 ( 
  
 AssetFieldType 
  
 fieldType 
 , 
  
 String 
  
 assetResourceName 
 , 
  
 String 
  
 assetGroupResourceName 
 ) 
  
 { 
  
 AssetGroupAsset 
  
 assetGroupAsset 
  
 = 
  
 AssetGroupAsset 
 . 
 newBuilder 
 () 
  
 . 
 setFieldType 
 ( 
 fieldType 
 ) 
  
 . 
 setAssetGroup 
 ( 
 assetGroupResourceName 
 ) 
  
 . 
 setAsset 
 ( 
 assetResourceName 
 ) 
  
 . 
 build 
 (); 
  
 AssetGroupAssetOperation 
  
 assetGroupAssetOperation 
  
 = 
  
 AssetGroupAssetOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 assetGroupAsset 
 ). 
 build 
 (); 
  
 return 
  
 MutateOperation 
 . 
 newBuilder 
 () 
  
 . 
 setAssetGroupAssetOperation 
 ( 
 assetGroupAssetOperation 
 ) 
  
 . 
 build 
 (); 
  
 } 
  
 /** Creates a MutateOperation to add a CampaignAsset. */ 
  
 MutateOperation 
  
 createCampaignAssetMutateOperation 
 ( 
  
 long 
  
 customerId 
 , 
  
 AssetFieldType 
  
 fieldType 
 , 
  
 String 
  
 assetResourceName 
 ) 
  
 { 
  
 CampaignAsset 
  
 campaignAsset 
  
 = 
  
 CampaignAsset 
 . 
 newBuilder 
 () 
  
 . 
 setFieldType 
 ( 
 fieldType 
 ) 
  
 . 
 setCampaign 
 ( 
 ResourceNames 
 . 
 campaign 
 ( 
 customerId 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 )) 
  
 . 
 setAsset 
 ( 
 assetResourceName 
 ) 
  
 . 
 build 
 (); 
  
 CampaignAssetOperation 
  
 campaignAssetOperation 
  
 = 
  
 CampaignAssetOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 campaignAsset 
 ). 
 build 
 (); 
  
 return 
  
 MutateOperation 
 . 
 newBuilder 
 (). 
 setCampaignAssetOperation 
 ( 
 campaignAssetOperation 
 ). 
 build 
 (); 
  
 } 
  
 /** 
 * Creates a list of MutateOperations that create {@link 
 * com.google.ads.googleads.v21.resources.AssetGroupSignal} objects. 
 */ 
  
 private 
  
 List<MutateOperation> 
  
 createAssetGroupSignalOperations 
 ( 
  
 long 
  
 customerId 
 , 
  
 String 
  
 assetGroupResourceName 
 , 
  
 Long 
  
 audienceId 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 mutateOperations 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 if 
  
 ( 
 audienceId 
  
 != 
  
 null 
 ) 
  
 { 
  
 // Creates an audience asset group signal. 
  
 // To learn more about Audience Signals, see: 
  
 // https://developers.google.com/google-ads/api/performance-max/asset-group-signals#audiences 
  
 AssetGroupSignal 
  
 audienceSignal 
  
 = 
  
 AssetGroupSignal 
 . 
 newBuilder 
 () 
  
 . 
 setAssetGroup 
 ( 
 assetGroupResourceName 
 ) 
  
 . 
 setAudience 
 ( 
  
 AudienceInfo 
 . 
 newBuilder 
 () 
  
 . 
 setAudience 
 ( 
 ResourceNames 
 . 
 audience 
 ( 
 customerId 
 , 
  
 audienceId 
 ))) 
  
 . 
 build 
 (); 
  
 mutateOperations 
 . 
 add 
 ( 
  
 MutateOperation 
 . 
 newBuilder 
 () 
  
 . 
 setAssetGroupSignalOperation 
 ( 
  
 AssetGroupSignalOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 audienceSignal 
 )) 
  
 . 
 build 
 ()); 
  
 } 
  
 // Creates a search theme asset group signal. 
  
 // To learn more about Search Themes Signals, see: 
  
 // https://developers.google.com/google-ads/api/performance-max/asset-group-signals#search_themes 
  
 AssetGroupSignal 
  
 searchThemeSignal 
  
 = 
  
 AssetGroupSignal 
 . 
 newBuilder 
 () 
  
 . 
 setAssetGroup 
 ( 
 assetGroupResourceName 
 ) 
  
 . 
 setSearchTheme 
 ( 
 SearchThemeInfo 
 . 
 newBuilder 
 (). 
 setText 
 ( 
 "travel" 
 ). 
 build 
 ()) 
  
 . 
 build 
 (); 
  
 mutateOperations 
 . 
 add 
 ( 
  
 MutateOperation 
 . 
 newBuilder 
 () 
  
 . 
 setAssetGroupSignalOperation 
 ( 
  
 AssetGroupSignalOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 searchThemeSignal 
 )) 
  
 . 
 build 
 ()); 
  
 return 
  
 mutateOperations 
 ; 
  
 } 
  
 /** 
 * Prints the details of a MutateGoogleAdsResponse. 
 * 
 * <p>Parses the "response" oneof field name and uses it to extract the new entity's name and 
 * resource name. 
 */ 
  
 private 
  
 void 
  
 printResponseDetails 
 ( 
 MutateGoogleAdsResponse 
  
 response 
 ) 
  
 { 
  
 // Parses the Mutate response to print details about the entities that were created by the 
  
 // request. 
  
 String 
  
 suffix 
  
 = 
  
 "_result" 
 ; 
  
 for 
  
 ( 
 MutateOperationResponse 
  
 result 
  
 : 
  
 response 
 . 
 getMutateOperationResponsesList 
 ()) 
  
 { 
  
 for 
  
 ( 
 Entry<FieldDescriptor 
 , 
  
 Object 
>  
 responseFields 
  
 : 
  
 result 
 . 
 getAllFields 
 (). 
 entrySet 
 ()) 
  
 { 
  
 String 
  
 fieldName 
  
 = 
  
 responseFields 
 . 
 getKey 
 (). 
 getName 
 (); 
  
 String 
  
 value 
  
 = 
  
 responseFields 
 . 
 getValue 
 (). 
 toString 
 (). 
 trim 
 (); 
  
 if 
  
 ( 
 fieldName 
 . 
 endsWith 
 ( 
 suffix 
 )) 
  
 { 
  
 fieldName 
  
 = 
  
 fieldName 
 . 
 substring 
 ( 
 0 
 , 
  
 fieldName 
 . 
 length 
 () 
  
 - 
  
 suffix 
 . 
 length 
 ()); 
  
 } 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
 "Created a(n) %s with %s.%n" 
 , 
  
 fieldName 
 , 
  
 value 
 ); 
  
 } 
  
 } 
  
 } 
  
 /** Returns the next temporary ID and decreases it by one. */ 
  
 private 
  
 long 
  
 getNextTemporaryId 
 () 
  
 { 
  
 return 
  
 temporaryId 
 -- 
 ; 
  
 } 
 } 
  
  

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 
  
 CommandLine 
 ; 
 using 
  
 Google.Ads.Gax.Examples 
 ; 
 using 
  
 Google.Ads.Gax.Util 
 ; 
 using 
  
 Google.Ads.GoogleAds.Config 
 ; 
 using 
  
 Google.Ads.GoogleAds.Lib 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Common 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Errors 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Resources 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Services 
 ; 
 using 
  
 Google.Protobuf 
 ; 
 using 
  
 System 
 ; 
 using 
  
 System.Collections.Generic 
 ; 
 using 
  
 System.Threading 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 AdvertisingChannelTypeEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 AssetFieldTypeEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 AssetGroupStatusEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 CampaignStatusEnum 
 . 
 Types 
 ; 
 using 
  
 static 
  
 Google 
 . 
 Ads 
 . 
 GoogleAds 
 . 
 V21 
 . 
 Enums 
 . 
 EuPoliticalAdvertisingStatusEnum 
 . 
 Types 
 ; 
 namespace 
  
 Google.Ads.GoogleAds.Examples.V21 
 { 
  
 /// <summary> 
  
 /// This example shows how to create a Performance Max campaign. 
  
 /// 
  
 /// For more information about Performance Max campaigns, see 
  
 /// https://developers.google.com/google-ads/api/docs/performance-max/overview 
  
 /// 
  
 /// Prerequisites: 
  
 /// - You must have at least one conversion action in the account. For 
  
 /// more about conversion actions, see 
  
 /// https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions 
  
 /// 
  
 /// This example uses the default customer conversion goals. For an example 
  
 /// of setting campaign-specific conversion goals, see 
  
 /// ShoppingAds/AddPerformanceMaxRetailCampaign.cs 
  
 /// </summary> 
  
 public 
  
 class 
  
 AddPerformanceMaxCampaign 
  
 : 
  
 ExampleBase 
  
 { 
  
 /// <summary> 
  
 /// Command line options for running the <see cref="AddPerformanceMaxCampaign"/> 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> 
  
 /// Optional: An audience ID to use to improve the targeting of the Performance Max 
  
 /// campaign. 
  
 /// </summary> 
  
 [Option("audienceId", Required = false, HelpText = "The ID of an audience.")] 
  
 public 
  
 long? 
  
 AudienceId 
  
 { 
  
 get 
 ; 
  
 set 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Optional: A boolean value indicating if the campaign is enabled for brand 
  
 /// guidelines. 
  
 /// </summary> 
  
 [Option("brandGuidelinesEnabled", Required = false, HelpText = 
 "A boolean value indicating if the campaign is enabled for brand guidelines.")] 
  
 public 
  
 bool 
  
 BrandGuidelinesEnabled 
  
 { 
  
 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 
 ); 
  
 AddPerformanceMaxCampaign 
  
 codeExample 
  
 = 
  
 new 
  
 AddPerformanceMaxCampaign 
 (); 
  
 Console 
 . 
 WriteLine 
 ( 
 codeExample 
 . 
 Description 
 ); 
  
 codeExample 
 . 
 Run 
 ( 
  
 new 
  
 GoogleAdsClient 
 (), 
  
 options 
 . 
 CustomerId 
 , 
  
 options 
 . 
 AudienceId 
 , 
  
 options 
 . 
 BrandGuidelinesEnabled 
  
 ); 
  
 } 
  
 // We specify temporary IDs that are specific to a single mutate request. Temporary IDs are 
  
 // always negative and unique within one mutate request. 
  
 // 
  
 // See https://developers.google.com/google-ads/api/docs/mutating/best-practices for further 
  
 // details. 
  
 // 
  
 // These temporary IDs are fixed because they are used in multiple places. 
  
 private 
  
 const 
  
 int 
  
 TEMPORARY_ID_BUDGET 
  
 = 
  
 - 
 1 
 ; 
  
 private 
  
 const 
  
 int 
  
 TEMPORARY_ID_CAMPAIGN 
  
 = 
  
 - 
 2 
 ; 
  
 private 
  
 const 
  
 int 
  
 TEMPORARY_ID_ASSET_GROUP 
  
 = 
  
 - 
 3 
 ; 
  
 // There are also entities that will be created in the same request but do not need to be 
  
 // fixed temporary IDs because they are referenced only once. 
  
 private 
  
 class 
  
 AssetTemporaryResourceNameGenerator 
  
 { 
  
 private 
  
 long 
  
 customerId 
 ; 
  
 private 
  
 long 
  
 next 
 ; 
  
 public 
  
 AssetTemporaryResourceNameGenerator 
 ( 
 long 
  
 customerId 
 , 
  
 long 
  
 assetGroupId 
 ) 
  
 { 
  
 this 
 . 
 customerId 
  
 = 
  
 customerId 
 ; 
  
 this 
 . 
 next 
  
 = 
  
 assetGroupId 
  
 - 
  
 1 
 ; 
  
 } 
  
 public 
  
 string 
  
 Next 
 () 
  
 { 
  
 long 
  
 i 
  
 = 
  
 next 
 ; 
  
 Interlocked 
 . 
 Decrement 
 ( 
 ref 
  
 next 
 ); 
  
 return 
  
 ResourceNames 
 . 
 Asset 
 ( 
 customerId 
 , 
  
 i 
 ); 
  
 } 
  
 } 
  
 /// <summary> 
  
 /// Returns a description about the code example. 
  
 /// </summary> 
  
 public 
  
 override 
  
 string 
  
 Description 
  
 = 
>  
 "This example shows how to create a Performance Max campaign." 
 ; 
  
 /// <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="audienceId">The optional audience ID.</param> 
  
 /// <param name="brandGuidelinesEnabled">Whether or not to enable brand guidelines.</param> 
  
 public 
  
 void 
  
 Run 
 ( 
 GoogleAdsClient 
  
 client 
 , 
  
 long 
  
 customerId 
 , 
  
 long? 
  
 audienceId 
 , 
  
 bool 
  
 brandGuidelinesEnabled 
 ) 
  
 { 
  
 try 
  
 { 
  
 GoogleAdsServiceClient 
  
 googleAdsServiceClient 
  
 = 
  
 client 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 GoogleAdsService 
 ); 
  
 // Performance Max campaigns require that repeated assets such as headlines and 
  
 // descriptions be created before the campaign. 
  
 // 
  
 // For the list of required assets for a Performance Max campaign, see 
  
 // https://developers.google.com/google-ads/api/docs/performance-max/assets 
  
 // 
  
 // Create the headlines. 
  
 List<string> 
  
 headlineAssetResourceNames 
  
 = 
  
 CreateMultipleTextAssets 
 ( 
  
 client 
 , 
  
 customerId 
 , 
  
 new 
 [] 
  
 { 
  
 "Travel" 
 , 
  
 "Travel Reviews" 
 , 
  
 "Book travel" 
  
 } 
  
 ); 
  
 // Create the descriptions. 
  
 List<string> 
  
 descriptionAssetResourceNames 
  
 = 
  
 CreateMultipleTextAssets 
 ( 
  
 client 
 , 
  
 customerId 
 , 
  
 new 
 [] 
  
 { 
  
 "Take to the air!" 
 , 
  
 "Fly to the sky!" 
  
 } 
  
 ); 
  
 string 
  
 tempResourceNameCampaignBudget 
  
 = 
  
 ResourceNames 
 . 
 CampaignBudget 
 ( 
  
 customerId 
 , 
  
 TEMPORARY_ID_BUDGET 
  
 ); 
  
 // 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 Performance Max campaign are closely tied to 
  
 // one-another, it is 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 
  
 MutateOperation 
  
 campaignBudgetOperation 
  
 = 
  
 CreateCampaignBudgetOperation 
 ( 
  
 tempResourceNameCampaignBudget 
  
 ); 
  
 string 
  
 tempResourceNameCampaign 
  
 = 
  
 ResourceNames 
 . 
 Campaign 
 ( 
  
 customerId 
 , 
  
 TEMPORARY_ID_CAMPAIGN 
  
 ); 
  
 MutateOperation 
  
 performanceMaxCampaignOperation 
  
 = 
  
 CreatePerformanceMaxCampaignOperation 
 ( 
  
 tempResourceNameCampaign 
 , 
  
 tempResourceNameCampaignBudget 
 , 
  
 brandGuidelinesEnabled 
  
 ); 
  
 List<MutateOperation> 
  
 campaignCriterionOperations 
  
 = 
  
 CreateCampaignCriterionOperations 
 ( 
 tempResourceNameCampaign 
 ); 
  
 List<MutateOperation> 
  
 assetGroupOperations 
  
 = 
  
 CreateAssetGroupOperations 
 ( 
  
 tempResourceNameCampaign 
 , 
  
 ResourceNames 
 . 
 AssetGroup 
 ( 
 customerId 
 , 
  
 TEMPORARY_ID_ASSET_GROUP 
 ), 
  
 headlineAssetResourceNames 
 , 
  
 descriptionAssetResourceNames 
 , 
  
 new 
  
 AssetTemporaryResourceNameGenerator 
 ( 
  
 customerId 
 , 
  
 TEMPORARY_ID_ASSET_GROUP 
  
 ), 
  
 client 
 . 
 Config 
 , 
  
 brandGuidelinesEnabled 
  
 ); 
  
 List<MutateOperation> 
  
 assetGroupSignalOperations 
  
 = 
  
 CreateAssetGroupSignalOperations 
 ( 
  
 customerId 
 , 
  
 ResourceNames 
 . 
 AssetGroup 
 ( 
 customerId 
 , 
  
 TEMPORARY_ID_ASSET_GROUP 
 ), 
  
 audienceId 
  
 ); 
  
 MutateGoogleAdsRequest 
  
 request 
  
 = 
  
 new 
  
 MutateGoogleAdsRequest 
  
 { 
  
 CustomerId 
  
 = 
  
 customerId 
 . 
 ToString 
 () 
  
 }; 
  
 // It's important to create these entities in this order because they depend on 
  
 // each other. 
  
 // 
  
 // Additionally, we take several lists of operations and flatten them into one 
  
 // large list. 
  
 request 
 . 
 MutateOperations 
 . 
 Add 
 ( 
 campaignBudgetOperation 
 ); 
  
 request 
 . 
 MutateOperations 
 . 
 Add 
 ( 
 performanceMaxCampaignOperation 
 ); 
  
 request 
 . 
 MutateOperations 
 . 
 AddRange 
 ( 
 campaignCriterionOperations 
 ); 
  
 request 
 . 
 MutateOperations 
 . 
 AddRange 
 ( 
 assetGroupOperations 
 ); 
  
 request 
 . 
 MutateOperations 
 . 
 AddRange 
 ( 
 assetGroupSignalOperations 
 ); 
  
 MutateGoogleAdsResponse 
  
 response 
  
 = 
  
 googleAdsServiceClient 
 . 
 Mutate 
 ( 
 request 
 ); 
  
 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> 
  
 /// 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="budgetResourceName">The temporary resource name of the budget to 
  
 /// create.</param> 
  
 /// <returns>A MutateOperation that creates a CampaignBudget.</returns> 
  
 private 
  
 MutateOperation 
  
 CreateCampaignBudgetOperation 
 ( 
 string 
  
 budgetResourceName 
 ) 
  
 { 
  
 MutateOperation 
  
 operation 
  
 = 
  
 new 
  
 MutateOperation 
  
 { 
  
 CampaignBudgetOperation 
  
 = 
  
 new 
  
 CampaignBudgetOperation 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 CampaignBudget 
  
 { 
  
 Name 
  
 = 
  
 "Performance Max campaign budget #" 
  
 + 
  
 ExampleUtilities 
 . 
 GetRandomString 
 (), 
  
 // The budget period already defaults to DAILY. 
  
 AmountMicros 
  
 = 
  
 50000000 
 , 
  
 // A Performance Max campaign cannot use a shared campaign budget. 
  
 ExplicitlyShared 
  
 = 
  
 false 
 , 
  
 // Set a temporary ID in the budget's resource name so it can be referenced 
  
 // by the campaign in later steps. 
  
 ResourceName 
  
 = 
  
 budgetResourceName 
  
 } 
  
 } 
  
 }; 
  
 return 
  
 operation 
 ; 
  
 } 
  
 /// Creates a MutateOperation that creates a new Performance Max campaign. 
  
 /// <param name="campaignResourceName">The campaign resource name.</param> 
  
 /// <param name="campaignBudgetResourceName">The campaign budget resource name.</param> 
  
 /// <param name="brandGuidelinesEnabled">Whether or not to enable brand guidelines.</param> 
  
 /// <returns>A MutateOperations that will create this new campaign.</returns> 
  
 private 
  
 MutateOperation 
  
 CreatePerformanceMaxCampaignOperation 
 ( 
  
 string 
  
 campaignResourceName 
 , 
  
 string 
  
 campaignBudgetResourceName 
 , 
  
 bool 
  
 brandGuidelinesEnabled 
 ) 
  
 { 
  
 MutateOperation 
  
 operation 
  
 = 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 CampaignOperation 
  
 = 
  
 new 
  
 CampaignOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 Campaign 
 () 
  
 { 
  
 Name 
  
 = 
  
 "Performance Max 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 
 , 
  
 // All Performance Max campaigns have an AdvertisingChannelType of 
  
 // PerformanceMax. The AdvertisingChannelSubType should not be set. 
  
 AdvertisingChannelType 
  
 = 
  
 AdvertisingChannelType 
 . 
 PerformanceMax 
 , 
  
 // Bidding strategy must be set directly on the campaign. Setting a 
  
 // portfolio bidding strategy by resource name is not supported. Max 
  
 // Conversion and Maximize Conversion Value are the only strategies 
  
 // supported for Performance Max campaigns. BiddingStrategyType is 
  
 // read-only and cannot be set by the API. An optional ROAS (Return on 
  
 // Advertising Spend) can be set to enable the MaximizeConversionValue 
  
 // bidding strategy. The ROAS value must be specified as a ratio in the API. 
  
 // It is calculated by dividing "total value" by "total spend". 
  
 // 
  
 // For more information on Maximize Conversion Value, see the support 
  
 // article: 
  
 // http://support.google.com/google-ads/answer/7684216. 
  
 // 
  
 // A target_roas of 3.5 corresponds to a 350% return on ad spend. 
  
 MaximizeConversionValue 
  
 = 
  
 new 
  
 MaximizeConversionValue 
 () 
  
 { 
  
 TargetRoas 
  
 = 
  
 3.5 
  
 }, 
  
 // Set the Final URL expansion opt out. This flag is specific to 
  
 // Performance Max campaigns. If opted out (True), only the final URLs in 
  
 // the asset group or URLs specified in the advertiser's Google Merchant 
  
 // Center or business data feeds are targeted. 
  
 // If opted in (False), the entire domain will be targeted. For best 
  
 // results, set this value to false to opt in and allow URL expansions. You 
  
 // can optionally add exclusions to limit traffic to parts of your website. 
  
 UrlExpansionOptOut 
  
 = 
  
 false 
 , 
  
 // Use the temporary resource name created earlier 
  
 ResourceName 
  
 = 
  
 campaignResourceName 
 , 
  
 // Set the budget using the given budget resource name. 
  
 CampaignBudget 
  
 = 
  
 campaignBudgetResourceName 
 , 
  
 // Set if the campaign is enabled for brand guidelines. For more information 
  
 // on brand guidelines, see https://support.google.com/google-ads/answer/14934472. 
  
 BrandGuidelinesEnabled 
  
 = 
  
 brandGuidelinesEnabled 
 , 
  
 // Declare whether or not this campaign contains political ads targeting the EU. 
  
 ContainsEuPoliticalAdvertising 
  
 = 
  
 EuPoliticalAdvertisingStatus 
 . 
 DoesNotContainEuPoliticalAdvertising 
 , 
  
 // Optional fields 
  
 StartDate 
  
 = 
  
 DateTime 
 . 
 Now 
 . 
 AddDays 
 ( 
 1 
 ). 
 ToString 
 ( 
 "yyyyMMdd" 
 ), 
  
 EndDate 
  
 = 
  
 DateTime 
 . 
 Now 
 . 
 AddDays 
 ( 
 365 
 ). 
 ToString 
 ( 
 "yyyyMMdd" 
 ) 
  
 } 
  
 } 
  
 }; 
  
 return 
  
 operation 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Creates a list of MutateOperations that create new campaign criteria. 
  
 /// </summary> 
  
 /// <param name="campaignResourceName">The campaign resource name.</param> 
  
 /// <returns>A list of MutateOperations that create new campaign criteria.</returns> 
  
 private 
  
 List<MutateOperation> 
  
 CreateCampaignCriterionOperations 
 ( 
  
 string 
  
 campaignResourceName 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 operations 
  
 = 
  
 new 
  
 List<MutateOperation> 
 (); 
  
 // Set the LOCATION campaign criteria. 
  
 // Target all of New York City except Brooklyn. 
  
 // Location IDs are listed here: 
  
 // https://developers.google.com/google-ads/api/reference/data/geotargets 
  
 // and they can also be retrieved using the GeoTargetConstantService as shown 
  
 // here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting 
  
 // 
  
 // We will add one positive location target for New York City (ID=1023191) 
  
 // and one negative location target for Brooklyn (ID=1022762). 
  
 // First, add the positive (negative = False) for New York City. 
  
 MutateOperation 
  
 operation1 
  
 = 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 CampaignCriterionOperation 
  
 = 
  
 new 
  
 CampaignCriterionOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 CampaignCriterion 
 () 
  
 { 
  
 Campaign 
  
 = 
  
 campaignResourceName 
 , 
  
 Location 
  
 = 
  
 new 
  
 LocationInfo 
 () 
  
 { 
  
 GeoTargetConstant 
  
 = 
  
 ResourceNames 
 . 
 GeoTargetConstant 
 ( 
 1023191 
 ) 
  
 }, 
  
 Negative 
  
 = 
  
 false 
  
 } 
  
 } 
  
 }; 
  
 operations 
 . 
 Add 
 ( 
 operation1 
 ); 
  
 // Next add the negative target for Brooklyn. 
  
 MutateOperation 
  
 operation2 
  
 = 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 CampaignCriterionOperation 
  
 = 
  
 new 
  
 CampaignCriterionOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 CampaignCriterion 
 () 
  
 { 
  
 Campaign 
  
 = 
  
 campaignResourceName 
 , 
  
 Location 
  
 = 
  
 new 
  
 LocationInfo 
 () 
  
 { 
  
 GeoTargetConstant 
  
 = 
  
 ResourceNames 
 . 
 GeoTargetConstant 
 ( 
 1022762 
 ) 
  
 }, 
  
 Negative 
  
 = 
  
 true 
  
 } 
  
 } 
  
 }; 
  
 operations 
 . 
 Add 
 ( 
 operation2 
 ); 
  
 // Set the LANGUAGE campaign criterion. 
  
 MutateOperation 
  
 operation3 
  
 = 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 CampaignCriterionOperation 
  
 = 
  
 new 
  
 CampaignCriterionOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 CampaignCriterion 
 () 
  
 { 
  
 Campaign 
  
 = 
  
 campaignResourceName 
 , 
  
 // Set the language. 
  
 // For a list of all language codes, see: 
  
 // https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 
  
 Language 
  
 = 
  
 new 
  
 LanguageInfo 
 () 
  
 { 
  
 LanguageConstant 
  
 = 
  
 ResourceNames 
 . 
 LanguageConstant 
 ( 
 1000 
 ) 
  
 // English 
  
 }, 
  
 } 
  
 } 
  
 }; 
  
 operations 
 . 
 Add 
 ( 
 operation3 
 ); 
  
 return 
  
 operations 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Creates multiple text assets and returns the list of resource names. 
  
 /// </summary> 
  
 /// <param name="client">The Google Ads Client.</param> 
  
 /// <param name="customerId">The customer's ID.</param> 
  
 /// <param name="texts">The texts to add.</param> 
  
 /// <returns>A list of asset resource names.</returns> 
  
 private 
  
 List<string> 
  
 CreateMultipleTextAssets 
 ( 
  
 GoogleAdsClient 
  
 client 
 , 
  
 long 
  
 customerId 
 , 
  
 string 
 [] 
  
 texts 
 ) 
  
 { 
  
 // Get the GoogleAdsService. 
  
 GoogleAdsServiceClient 
  
 googleAdsServiceClient 
  
 = 
  
 client 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 GoogleAdsService 
 ); 
  
 MutateGoogleAdsRequest 
  
 request 
  
 = 
  
 new 
  
 MutateGoogleAdsRequest 
 () 
  
 { 
  
 CustomerId 
  
 = 
  
 customerId 
 . 
 ToString 
 () 
  
 }; 
  
 foreach 
  
 ( 
 string 
  
 text 
  
 in 
  
 texts 
 ) 
  
 { 
  
 request 
 . 
 MutateOperations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetOperation 
  
 = 
  
 new 
  
 AssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 Asset 
 () 
  
 { 
  
 TextAsset 
  
 = 
  
 new 
  
 TextAsset 
 () 
  
 { 
  
 Text 
  
 = 
  
 text 
  
 } 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 } 
  
 // Send the operations in a single Mutate request. 
  
 MutateGoogleAdsResponse 
  
 response 
  
 = 
  
 googleAdsServiceClient 
 . 
 Mutate 
 ( 
 request 
 ); 
  
 List<string> 
  
 assetResourceNames 
  
 = 
  
 new 
  
 List<string> 
 (); 
  
 foreach 
  
 ( 
 MutateOperationResponse 
  
 operationResponse 
  
 in 
  
 response 
 . 
 MutateOperationResponses 
 ) 
  
 { 
  
 MutateAssetResult 
  
 assetResult 
  
 = 
  
 operationResponse 
 . 
 AssetResult 
 ; 
  
 assetResourceNames 
 . 
 Add 
 ( 
 assetResult 
 . 
 ResourceName 
 ); 
  
 } 
  
 PrintResponseDetails 
 ( 
 response 
 ); 
  
 return 
  
 assetResourceNames 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Creates a list of MutateOperations that create a new asset_group. 
  
 /// </summary> 
  
 /// <param name="campaignResourceName">The campaign resource name.</param> 
  
 /// <param name="assetGroupResourceName">The asset group resource name.</param> 
  
 /// <param name="headlineAssetResourceNames">The headline asset resource names.</param> 
  
 /// <param name="descriptionAssetResourceNames">The description asset resource 
  
 /// names.</param> 
  
 /// <param name="resourceNameGenerator">A generator for unique temporary ID's.</param> 
  
 /// <param name="config">The Google Ads config.</param> 
  
 /// <param name="brandGuidelinesEnabled">Whether or not to enable brand guidelines.</param> 
  
 /// <returns>A list of MutateOperations that create the new asset group.</returns> 
  
 private 
  
 List<MutateOperation> 
  
 CreateAssetGroupOperations 
 ( 
  
 string 
  
 campaignResourceName 
 , 
  
 string 
  
 assetGroupResourceName 
 , 
  
 List<string> 
  
 headlineAssetResourceNames 
 , 
  
 List<string> 
  
 descriptionAssetResourceNames 
 , 
  
 AssetTemporaryResourceNameGenerator 
  
 resourceNameGenerator 
 , 
  
 GoogleAdsConfig 
  
 config 
 , 
  
 bool 
  
 brandGuidelinesEnabled 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 operations 
  
 = 
  
 new 
  
 List<MutateOperation> 
 (); 
  
 // Create the AssetGroup 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetGroupOperation 
  
 = 
  
 new 
  
 AssetGroupOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AssetGroup 
 () 
  
 { 
  
 Name 
  
 = 
  
 "Performance Max asset group #" 
  
 + 
  
 ExampleUtilities 
 . 
 GetRandomString 
 (), 
  
 Campaign 
  
 = 
  
 campaignResourceName 
 , 
  
 FinalUrls 
  
 = 
  
 { 
  
 "http://www.example.com" 
  
 }, 
  
 FinalMobileUrls 
  
 = 
  
 { 
  
 "http://www.example.com" 
  
 }, 
  
 Status 
  
 = 
  
 AssetGroupStatus 
 . 
 Paused 
 , 
  
 ResourceName 
  
 = 
  
 assetGroupResourceName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 // For the list of required assets for a Performance Max campaign, see 
  
 // https://developers.google.com/google-ads/api/docs/performance-max/assets 
  
 // An AssetGroup is linked to an Asset by creating a new AssetGroupAsset 
  
 // and providing: 
  
 //   the resource name of the AssetGroup 
  
 //   the resource name of the Asset 
  
 //   the field_type of the Asset in this AssetGroup. 
  
 // 
  
 // To learn more about AssetGroups, see 
  
 // https://developers.google.com/google-ads/api/docs/performance-max/asset-groups 
  
 // Link the previously created multiple text assets. 
  
 // Link the headline assets. 
  
 foreach 
  
 ( 
 string 
  
 resourceName 
  
 in 
  
 headlineAssetResourceNames 
 ) 
  
 { 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetGroupAssetOperation 
  
 = 
  
 new 
  
 AssetGroupAssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AssetGroupAsset 
 () 
  
 { 
  
 FieldType 
  
 = 
  
 AssetFieldType 
 . 
 Headline 
 , 
  
 AssetGroup 
  
 = 
  
 assetGroupResourceName 
 , 
  
 Asset 
  
 = 
  
 resourceName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 } 
  
 // Link the description assets. 
  
 foreach 
  
 ( 
 string 
  
 resourceName 
  
 in 
  
 descriptionAssetResourceNames 
 ) 
  
 { 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetGroupAssetOperation 
  
 = 
  
 new 
  
 AssetGroupAssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AssetGroupAsset 
 () 
  
 { 
  
 FieldType 
  
 = 
  
 AssetFieldType 
 . 
 Description 
 , 
  
 AssetGroup 
  
 = 
  
 assetGroupResourceName 
 , 
  
 Asset 
  
 = 
  
 resourceName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 } 
  
 // Create and link the brand assets. 
  
 operations 
 . 
 AddRange 
 ( 
  
 CreateAndLinkBrandAssets 
 ( 
  
 assetGroupResourceName 
 , 
  
 campaignResourceName 
 , 
  
 resourceNameGenerator 
 , 
  
 "Interplanetary Cruises" 
 , 
  
 "https://gaagl.page.link/bjYi" 
 , 
  
 "Marketing Logo" 
 , 
  
 config 
 , 
  
 brandGuidelinesEnabled 
  
 ) 
  
 ); 
  
 // Create and link the long headline text asset. 
  
 operations 
 . 
 AddRange 
 ( 
  
 CreateAndLinkTextAsset 
 ( 
  
 assetGroupResourceName 
 , 
  
 resourceNameGenerator 
 . 
 Next 
 (), 
  
 "Travel the World" 
 , 
  
 AssetFieldType 
 . 
 LongHeadline 
  
 ) 
  
 ); 
  
 // Create and link the image assets. 
  
 // Create and link the Marketing Image Asset. 
  
 operations 
 . 
 AddRange 
 ( 
  
 CreateAndLinkImageAsset 
 ( 
  
 assetGroupResourceName 
 , 
  
 resourceNameGenerator 
 . 
 Next 
 (), 
  
 "https://gaagl.page.link/Eit5" 
 , 
  
 AssetFieldType 
 . 
 MarketingImage 
 , 
  
 "Marketing Image" 
 , 
  
 config 
  
 ) 
  
 ); 
  
 // Create and link the Square Marketing Image Asset. 
  
 operations 
 . 
 AddRange 
 ( 
  
 CreateAndLinkImageAsset 
 ( 
  
 assetGroupResourceName 
 , 
  
 resourceNameGenerator 
 . 
 Next 
 (), 
  
 "https://gaagl.page.link/bjYi" 
 , 
  
 AssetFieldType 
 . 
 SquareMarketingImage 
 , 
  
 "Square Marketing Image" 
 , 
  
 config 
  
 ) 
  
 ); 
  
 return 
  
 operations 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Creates a list of MutateOperations that create a new linked text asset. 
  
 /// </summary> 
  
 /// <param name="assetGroupResourceName">The resource name of the asset group to be 
  
 /// created.</param> 
  
 /// <param name="assetResourceName">The resource name of the text asset to be 
  
 /// created.</param> 
  
 /// <param name="text">The text of the asset to be created.</param> 
  
 /// <param name="fieldType">The field type of the asset to be created.</param> 
  
 /// <returns>A list of MutateOperations that create the new linked text asset.</returns> 
  
 private 
  
 List<MutateOperation> 
  
 CreateAndLinkTextAsset 
 ( 
  
 string 
  
 assetGroupResourceName 
 , 
  
 string 
  
 assetResourceName 
 , 
  
 string 
  
 text 
 , 
  
 AssetFieldType 
  
 fieldType 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 operations 
  
 = 
  
 new 
  
 List<MutateOperation> 
 (); 
  
 // Create the Text Asset. 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetOperation 
  
 = 
  
 new 
  
 AssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 Asset 
 () 
  
 { 
  
 ResourceName 
  
 = 
  
 assetResourceName 
 , 
  
 TextAsset 
  
 = 
  
 new 
  
 TextAsset 
 () 
  
 { 
  
 Text 
  
 = 
  
 text 
  
 } 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 // Create an AssetGroupAsset to link the Asset to the AssetGroup. 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetGroupAssetOperation 
  
 = 
  
 new 
  
 AssetGroupAssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AssetGroupAsset 
 () 
  
 { 
  
 FieldType 
  
 = 
  
 fieldType 
 , 
  
 AssetGroup 
  
 = 
  
 assetGroupResourceName 
 , 
  
 Asset 
  
 = 
  
 assetResourceName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 return 
  
 operations 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Creates a list of MutateOperations that create a new linked image asset. 
  
 /// </summary> 
  
 /// <param name="assetGroupResourceName">The resource name of the asset group to be 
  
 /// created.</param> 
  
 /// <param name="assetResourceName">The resource name of the text asset to be 
  
 /// created.</param> 
  
 /// <param name="url">The url of the image to be retrieved and put into an asset.</param> 
  
 /// <param name="fieldType">The field type of the asset to be created.</param> 
  
 /// <param name="assetName">The asset name.</param> 
  
 /// <param name="config">The Google Ads Config.</param> 
  
 /// <returns>A list of MutateOperations that create a new linked image asset.</returns> 
  
 private 
  
 List<MutateOperation> 
  
 CreateAndLinkImageAsset 
 ( 
  
 string 
  
 assetGroupResourceName 
 , 
  
 string 
  
 assetResourceName 
 , 
  
 string 
  
 url 
 , 
  
 AssetFieldType 
  
 fieldType 
 , 
  
 string 
  
 assetName 
 , 
  
 GoogleAdsConfig 
  
 config 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 operations 
  
 = 
  
 new 
  
 List<MutateOperation> 
 (); 
  
 // Create the Image Asset. 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetOperation 
  
 = 
  
 new 
  
 AssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 Asset 
 () 
  
 { 
  
 ResourceName 
  
 = 
  
 assetResourceName 
 , 
  
 ImageAsset 
  
 = 
  
 new 
  
 ImageAsset 
 () 
  
 { 
  
 Data 
  
 = 
  
 ByteString 
 . 
 CopyFrom 
 ( 
  
 MediaUtilities 
 . 
 GetAssetDataFromUrl 
 ( 
 url 
 , 
  
 config 
 ) 
  
 ) 
  
 }, 
  
 // Provide a unique friendly name to identify your asset. 
  
 // When there is an existing image asset with the same content but a 
  
 // different name, the new name will be dropped silently. 
  
 Name 
  
 = 
  
 assetName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 // Create an AssetGroupAsset to link the Asset to the AssetGroup. 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetGroupAssetOperation 
  
 = 
  
 new 
  
 AssetGroupAssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AssetGroupAsset 
 () 
  
 { 
  
 FieldType 
  
 = 
  
 fieldType 
 , 
  
 AssetGroup 
  
 = 
  
 assetGroupResourceName 
 , 
  
 Asset 
  
 = 
  
 assetResourceName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 return 
  
 operations 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Creates a list of MutateOperations that create and link the brand assets. 
  
 /// </summary> 
  
 /// <param name="assetGroupResourceName">The resource name of the asset group to link assets 
  
 /// to.</param> 
  
 /// <param name="campaignResourceName">The resource name of the campaign to link assets 
  
 /// to.</param> 
  
 /// <param name="assetResourceNameGenerator">The resource name generator of the assets to be 
  
 /// created.</param> 
  
 /// <param name="businessName">The business name text to be put into an asset.</param> 
  
 /// <param name="logoUrl">The url of the logo to be retrieved and put into an asset.</param> 
  
 /// <param name="logoName">The asset name of the logo.</param> 
  
 /// <param name="config">The Google Ads Config.</param> 
  
 /// <param name="brandGuidelinesEnabled">Whether or not to enable brand guidelines.</param> 
  
 /// <returns>A list of MutateOperations that create a new linked image asset.</returns> 
  
 private 
  
 List<MutateOperation> 
  
 CreateAndLinkBrandAssets 
 ( 
  
 string 
  
 assetGroupResourceName 
 , 
  
 string 
  
 campaignResourceName 
 , 
  
 AssetTemporaryResourceNameGenerator 
  
 assetResourceNameGenerator 
 , 
  
 string 
  
 businessName 
 , 
  
 string 
  
 logoUrl 
 , 
  
 string 
  
 logoName 
 , 
  
 GoogleAdsConfig 
  
 config 
 , 
  
 bool 
  
 brandGuidelinesEnabled 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 operations 
  
 = 
  
 new 
  
 List<MutateOperation> 
 (); 
  
 string 
  
 logoAssetResourceName 
  
 = 
  
 assetResourceNameGenerator 
 . 
 Next 
 (); 
  
 string 
  
 businessNameAssetResourceName 
  
 = 
  
 assetResourceNameGenerator 
 . 
 Next 
 (); 
  
 // Create the Image Asset. 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetOperation 
  
 = 
  
 new 
  
 AssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 Asset 
 () 
  
 { 
  
 ResourceName 
  
 = 
  
 logoAssetResourceName 
 , 
  
 ImageAsset 
  
 = 
  
 new 
  
 ImageAsset 
 () 
  
 { 
  
 Data 
  
 = 
  
 ByteString 
 . 
 CopyFrom 
 ( 
  
 MediaUtilities 
 . 
 GetAssetDataFromUrl 
 ( 
 logoUrl 
 , 
  
 config 
 ) 
  
 ) 
  
 }, 
  
 // Provide a unique friendly name to identify your asset. 
  
 // When there is an existing image asset with the same content but a 
  
 // different name, the new name will be dropped silently. 
  
 Name 
  
 = 
  
 logoName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 // Create the business name asset. 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetOperation 
  
 = 
  
 new 
  
 AssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 Asset 
 () 
  
 { 
  
 ResourceName 
  
 = 
  
 businessNameAssetResourceName 
 , 
  
 TextAsset 
  
 = 
  
 new 
  
 TextAsset 
 () 
  
 { 
  
 Text 
  
 = 
  
 businessName 
 , 
  
 } 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 if 
  
 ( 
 brandGuidelinesEnabled 
 ) 
  
 { 
  
 // Create CampaignAssets to link the Assets to the Campaign. 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 CampaignAssetOperation 
  
 = 
  
 new 
  
 CampaignAssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 CampaignAsset 
 () 
  
 { 
  
 FieldType 
  
 = 
  
 AssetFieldType 
 . 
 Logo 
 , 
  
 Campaign 
  
 = 
  
 campaignResourceName 
 , 
  
 Asset 
  
 = 
  
 logoAssetResourceName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 CampaignAssetOperation 
  
 = 
  
 new 
  
 CampaignAssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 CampaignAsset 
 () 
  
 { 
  
 FieldType 
  
 = 
  
 AssetFieldType 
 . 
 BusinessName 
 , 
  
 Campaign 
  
 = 
  
 campaignResourceName 
 , 
  
 Asset 
  
 = 
  
 businessNameAssetResourceName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 } 
  
 else 
  
 { 
  
 // Create AssetGroupAssets to link the Assets to the AssetGroup. 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetGroupAssetOperation 
  
 = 
  
 new 
  
 AssetGroupAssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AssetGroupAsset 
 () 
  
 { 
  
 FieldType 
  
 = 
  
 AssetFieldType 
 . 
 Logo 
 , 
  
 AssetGroup 
  
 = 
  
 assetGroupResourceName 
 , 
  
 Asset 
  
 = 
  
 logoAssetResourceName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetGroupAssetOperation 
  
 = 
  
 new 
  
 AssetGroupAssetOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AssetGroupAsset 
 () 
  
 { 
  
 FieldType 
  
 = 
  
 AssetFieldType 
 . 
 BusinessName 
 , 
  
 AssetGroup 
  
 = 
  
 assetGroupResourceName 
 , 
  
 Asset 
  
 = 
  
 businessNameAssetResourceName 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 } 
  
 return 
  
 operations 
 ; 
  
 } 
  
 /// <summary> 
  
 /// Creates a list of MutateOperations that may create AssetGroupSignals 
  
 /// </summary> 
  
 /// <param name="customerId">The customer ID.</param> 
  
 /// <param name="assetGroupResourceName">The resource name of the asset group to be 
  
 /// created.</param> 
  
 /// <param name="audienceId">The optional audience ID.</param> 
  
 /// <returns>A list of MutateOperations that create may create AssetGroupSignals.</returns> 
  
 private 
  
 List<MutateOperation> 
  
 CreateAssetGroupSignalOperations 
 ( 
  
 long 
  
 customerId 
 , 
  
 string 
  
 assetGroupResourceName 
 , 
  
 long? 
  
 audienceId 
 ) 
  
 { 
  
 List<MutateOperation> 
  
 operations 
  
 = 
  
 new 
  
 List<MutateOperation> 
 (); 
  
 if 
  
 ( 
 audienceId 
 . 
 HasValue 
 ) 
  
 { 
  
 // Create an audience asset group signal. 
  
 // To learn more about Audience Signals, see 
  
 // https://developers.google.com/google-ads/api/docs/performance-max/asset-groups#audience_signals 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetGroupSignalOperation 
  
 = 
  
 new 
  
 AssetGroupSignalOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AssetGroupSignal 
 () 
  
 { 
  
 AssetGroup 
  
 = 
  
 assetGroupResourceName 
 , 
  
 Audience 
  
 = 
  
 new 
  
 AudienceInfo 
 () 
  
 { 
  
 Audience 
  
 = 
  
 ResourceNames 
 . 
 Audience 
 ( 
 customerId 
 , 
  
 audienceId 
 . 
 Value 
 ) 
  
 } 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 } 
  
 // Create a search theme asset group signal. 
  
 // To learn more about Search Themes Signals, see: 
  
 // https://developers.google.com/google-ads/api/performance-max/asset-group-signals#search_themes 
  
 operations 
 . 
 Add 
 ( 
  
 new 
  
 MutateOperation 
 () 
  
 { 
  
 AssetGroupSignalOperation 
  
 = 
  
 new 
  
 AssetGroupSignalOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 AssetGroupSignal 
 () 
  
 { 
  
 AssetGroup 
  
 = 
  
 assetGroupResourceName 
 , 
  
 SearchTheme 
  
 = 
  
 new 
  
 SearchThemeInfo 
 () 
  
 { 
  
 Text 
  
 = 
  
 "travel" 
  
 } 
  
 } 
  
 } 
  
 } 
  
 ); 
  
 return 
  
 operations 
 ; 
  
 } 
  
 /// <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 
  
 entityName 
  
 = 
  
 operationResponse 
 . 
 ResponseCase 
 . 
 ToString 
 (); 
  
 // Trim the substring "Result" from the end of the entity name. 
  
 entityName 
  
 = 
  
 entityName 
 . 
 Remove 
 ( 
 entityName 
 . 
 Length 
  
 - 
  
 6 
 ); 
  
 string 
  
 resourceName 
 ; 
  
 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 
 ; 
  
 case 
  
 MutateOperationResponse 
 . 
 ResponseOneofCase 
 . 
 AssetResult 
 : 
  
 resourceName 
  
 = 
  
 operationResponse 
 . 
 AssetResult 
 . 
 ResourceName 
 ; 
  
 break 
 ; 
  
 case 
  
 MutateOperationResponse 
 . 
 ResponseOneofCase 
 . 
 AssetGroupResult 
 : 
  
 resourceName 
  
 = 
  
 operationResponse 
 . 
 AssetGroupResult 
 . 
 ResourceName 
 ; 
  
 break 
 ; 
  
 case 
  
 MutateOperationResponse 
 . 
 ResponseOneofCase 
 . 
 AssetGroupAssetResult 
 : 
  
 resourceName 
  
 = 
  
 operationResponse 
 . 
 AssetGroupAssetResult 
 . 
 ResourceName 
 ; 
  
 break 
 ; 
  
 default 
 : 
  
 resourceName 
  
 = 
  
 "<not found>" 
 ; 
  
 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\V21\ResourceNames; 
 use Google\Ads\GoogleAds\V21\Common\AudienceInfo; 
 use Google\Ads\GoogleAds\V21\Common\ImageAsset; 
 use Google\Ads\GoogleAds\V21\Common\LanguageInfo; 
 use Google\Ads\GoogleAds\V21\Common\LocationInfo; 
 use Google\Ads\GoogleAds\V21\Common\MaximizeConversionValue; 
 use Google\Ads\GoogleAds\V21\Common\TextAsset; 
 use Google\Ads\GoogleAds\V21\Enums\AdvertisingChannelTypeEnum\AdvertisingChannelType; 
 use Google\Ads\GoogleAds\V21\Enums\AssetFieldTypeEnum\AssetFieldType; 
 use Google\Ads\GoogleAds\V21\Enums\AssetGroupStatusEnum\AssetGroupStatus; 
 use Google\Ads\GoogleAds\V21\Enums\BudgetDeliveryMethodEnum\BudgetDeliveryMethod; 
 use Google\Ads\GoogleAds\V21\Enums\CampaignStatusEnum\CampaignStatus; 
 use Google\Ads\GoogleAds\V21\Enums\EuPoliticalAdvertisingStatusEnum\EuPoliticalAdvertisingStatus; 
 use Google\Ads\GoogleAds\V21\Errors\GoogleAdsError; 
 use Google\Ads\GoogleAds\V21\Resources\Asset; 
 use Google\Ads\GoogleAds\V21\Resources\AssetGroup; 
 use Google\Ads\GoogleAds\V21\Resources\AssetGroupAsset; 
 use Google\Ads\GoogleAds\V21\Resources\AssetGroupSignal; 
 use Google\Ads\GoogleAds\V21\Resources\Campaign; 
 use Google\Ads\GoogleAds\V21\Resources\CampaignAsset; 
 use Google\Ads\GoogleAds\V21\Resources\CampaignBudget; 
 use Google\Ads\GoogleAds\V21\Resources\CampaignCriterion; 
 use Google\Ads\GoogleAds\V21\Services\AssetGroupAssetOperation; 
 use Google\Ads\GoogleAds\V21\Services\AssetGroupOperation; 
 use Google\Ads\GoogleAds\V21\Services\AssetGroupSignalOperation; 
 use Google\Ads\GoogleAds\V21\Services\AssetOperation; 
 use Google\Ads\GoogleAds\V21\Services\CampaignAssetOperation; 
 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\ApiCore\ApiException; 
 use Google\ApiCore\Serializer; 
 /** 
 * This example shows how to create a Performance Max campaign. 
 * 
 * For more information about Performance Max campaigns, see 
 * https://developers.google.com/google-ads/api/docs/performance-max/overview. 
 * 
 * Prerequisites: 
 * - You must have at least one conversion action in the account. For more about conversion actions, 
 * see 
 * https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions. 
 * 
 * This example uses the default customer conversion goals. For an example of setting 
 * campaign-specific conversion goals, see ShoppingAds/AddPerformanceMaxRetailCampaign.php. 
 */ 
 class AddPerformanceMaxCampaign 
 { 
 private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE'; 
 // Optional: An audience ID to use to improve the targeting of the Performance Max campaign. 
 private const AUDIENCE_ID = null; 
 // Optional: Indicates whether the created campaign is enabled for brand guidelines. 
 private const BRAND_GUIDELINES_ENABLED = false; 
 // We specify temporary IDs that are specific to a single mutate request. 
 // Temporary IDs are always negative and unique within one mutate request. 
 // 
 // See https://developers.google.com/google-ads/api/docs/mutating/best-practices 
 // for further details. 
 // 
 // These temporary IDs are fixed because they are used in multiple places. 
 private const BUDGET_TEMPORARY_ID = -1; 
 private const PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID = -2; 
 private const ASSET_GROUP_TEMPORARY_ID = -3; 
 // There are also entities that will be created in the same request but do not need to be fixed 
 // temporary IDs because they are referenced only once. 
 /** @var int the negative temporary ID used in bulk mutates. */ 
 private static $nextTempId = self::ASSET_GROUP_TEMPORARY_ID - 1; 
 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::AUDIENCE_ID => GetOpt::OPTIONAL_ARGUMENT, 
 ArgumentNames::BRAND_GUIDELINES_ENABLED => GetOpt::OPTIONAL_ARGUMENT 
 ]); 
 // 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::AUDIENCE_ID] ?: self::AUDIENCE_ID, 
 filter_var( 
 $options[ArgumentNames::BRAND_GUIDELINES_ENABLED] 
 ?: self::BRAND_GUIDELINES_ENABLED, 
 FILTER_VALIDATE_BOOLEAN 
 ) 
 ); 
 } 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 int|null $audienceId the audience ID 
 * @param bool $brandGuidelinesEnabled whether the created campaign will be enabled for brand 
 *     guidelines 
 */ 
 public static function runExample( 
 GoogleAdsClient $googleAdsClient, 
 int $customerId, 
 ?int $audienceId, 
 bool $brandGuidelinesEnabled 
 ) { 
 // Performance Max campaigns require that repeated assets such as headlines 
 // and descriptions be created before the campaign. 
 // For the list of required assets for a Performance Max campaign, see 
 // https://developers.google.com/google-ads/api/docs/performance-max/assets. 
 // 
 // Creates the headlines. 
 $headlineAssetResourceNames = self::createMultipleTextAssets( 
 $googleAdsClient, 
 $customerId, 
 ["Travel", "Travel Reviews", "Book travel"] 
 ); 
 // Creates the descriptions. 
 $descriptionAssetResourceNames = self::createMultipleTextAssets( 
 $googleAdsClient, 
 $customerId, 
 ["Take to the air!", "Fly to the sky!"] 
 ); 
 // It's important to create the below entities in this order because they depend on 
 // each other. 
 $operations = []; 
 // 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 Performance Max 
 // 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. 
 $operations[] = self::createCampaignBudgetOperation($customerId); 
 $operations[] = 
 self::createPerformanceMaxCampaignOperation($customerId, $brandGuidelinesEnabled); 
 $operations = 
 array_merge($operations, self::createCampaignCriterionOperations($customerId)); 
 $operations = array_merge($operations, self::createAssetGroupOperations( 
 $customerId, 
 $headlineAssetResourceNames, 
 $descriptionAssetResourceNames, 
 $brandGuidelinesEnabled 
 )); 
 $operations = array_merge($operations, self::createAssetGroupSignalOperations( 
 $customerId, 
 ResourceNames::forAssetGroup($customerId, self::ASSET_GROUP_TEMPORARY_ID), 
 $audienceId 
 )); 
 // Issues a mutate request to create everything and prints its information. 
 $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); 
 $response = $googleAdsServiceClient->mutate(MutateGoogleAdsRequest::build( 
 $customerId, 
 $operations 
 )); 
 self::printResponseDetails($response); 
 } 
 /** 
 * 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 
 * @return MutateOperation the mutate operation that creates a campaign budget 
 */ 
 private static function createCampaignBudgetOperation(int $customerId): MutateOperation 
 { 
 // Creates a mutate operation that creates a campaign budget operation. 
 return new MutateOperation([ 
 'campaign_budget_operation' => new CampaignBudgetOperation([ 
 'create' => new CampaignBudget([ 
 // 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 
 ), 
 'name' => 'Performance Max campaign budget #' . Helper::getPrintableDatetime(), 
 // The budget period already defaults to DAILY. 
 'amount_micros' => 50000000, 
 'delivery_method' => BudgetDeliveryMethod::STANDARD, 
 // A Performance Max campaign cannot use a shared campaign budget. 
 'explicitly_shared' => false 
 ]) 
 ]) 
 ]); 
 } 
 /** 
 * Creates a MutateOperation that creates a new Performance Max 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 
 * @param bool $brandGuidelinesEnabled whether the created campaign will be enabled for brand 
 *     guidelines 
 * @return MutateOperation the mutate operation that creates the campaign 
 */ 
 private static function createPerformanceMaxCampaignOperation( 
 int $customerId, 
 bool $brandGuidelinesEnabled 
 ): MutateOperation { 
 // Creates a mutate operation that creates a campaign operation. 
 return new MutateOperation([ 
 'campaign_operation' => new CampaignOperation([ 
 'create' => new Campaign([ 
 'name' => 'Performance Max campaign #' . Helper::getPrintableDatetime(), 
 // Assigns the resource name with a temporary ID. 
 'resource_name' => ResourceNames::forCampaign( 
 $customerId, 
 self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ), 
 // Sets the budget using the given budget resource name. 
 'campaign_budget' => ResourceNames::forCampaignBudget( 
 $customerId, 
 self::BUDGET_TEMPORARY_ID 
 ), 
 // The campaign is the only entity in the mutate request that should have its 
 // status set. 
 // Recommendation: Set the campaign to PAUSED when creating it to prevent 
 // the ads from immediately serving. 
 'status' => CampaignStatus::PAUSED, 
 // All Performance Max campaigns have an advertising_channel_type of 
 // PERFORMANCE_MAX. The advertising_channel_sub_type should not be set. 
 'advertising_channel_type' => AdvertisingChannelType::PERFORMANCE_MAX, 
 // Bidding strategy must be set directly on the campaign. 
 // Setting a portfolio bidding strategy by resource name is not supported. 
 // Max Conversion and Maximize Conversion Value are the only strategies 
 // supported for Performance Max campaigns. 
 // An optional ROAS (Return on Advertising Spend) can be set for 
 // maximize_conversion_value. The ROAS value must be specified as a ratio in 
 // the API. It is calculated by dividing "total value" by "total spend". 
 // For more information on Maximize Conversion Value, see the support 
 // article: http://support.google.com/google-ads/answer/7684216. 
 // A target_roas of 3.5 corresponds to a 350% return on ad spend. 
 'maximize_conversion_value' => new MaximizeConversionValue([ 
 'target_roas' => 3.5 
 ]), 
 // Sets the Final URL expansion opt out. This flag is specific to 
 // Performance Max campaigns. If opted out (true), only the final URLs in 
 // the asset group or URLs specified in the advertiser's Google Merchant 
 // Center or business data feeds are targeted. 
 // If opted in (false), the entire domain will be targeted. For best 
 // results, set this value to false to opt in and allow URL expansions. You 
 // can optionally add exclusions to limit traffic to parts of your website. 
 'url_expansion_opt_out' => false, 
 // Sets if the campaign is enabled for brand guidelines. For more information 
 // on brand guidelines, see 
 // https://support.google.com/google-ads/answer/14934472. 
 'brand_guidelines_enabled' => $brandGuidelinesEnabled, 
 // Declare whether or not this campaign serves political ads targeting the EU. 
 'contains_eu_political_advertising' = 
> EuPoliticalAdvertisingStatus::DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING, 
 // Optional fields. 
 'start_date' => date('Ymd', strtotime('+1 day')), 
 'end_date' => date('Ymd', strtotime('+365 days')) 
 ]) 
 ]) 
 ]); 
 } 
 /** 
 * Creates a list of MutateOperations that create new campaign criteria. 
 * 
 * @param int $customerId the customer ID 
 * @return MutateOperation[] a list of MutateOperations that create the new campaign criteria 
 */ 
 private static function createCampaignCriterionOperations(int $customerId): array 
 { 
 $operations = []; 
 // Set the LOCATION campaign criteria. 
 // Target all of New York City except Brooklyn. 
 // Location IDs are listed here: 
 // https://developers.google.com/google-ads/api/reference/data/geotargets 
 // and they can also be retrieved using the GeoTargetConstantService as shown 
 // here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting 
 // 
 // We will add one positive location target for New York City (ID=1023191) 
 // and one negative location target for Brooklyn (ID=1022762). 
 // First, adds the positive (negative = false) for New York City. 
 $operations[] = new MutateOperation([ 
 'campaign_criterion_operation' => new CampaignCriterionOperation([ 
 'create' => new CampaignCriterion([ 
 'campaign' => ResourceNames::forCampaign( 
 $customerId, 
 self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ), 
 'location' => new LocationInfo([ 
 'geo_target_constant' => ResourceNames::forGeoTargetConstant(1023191) 
 ]), 
 'negative' => false 
 ]) 
 ]) 
 ]); 
 // Next adds the negative target for Brooklyn. 
 $operations[] = new MutateOperation([ 
 'campaign_criterion_operation' => new CampaignCriterionOperation([ 
 'create' => new CampaignCriterion([ 
 'campaign' => ResourceNames::forCampaign( 
 $customerId, 
 self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ), 
 'location' => new LocationInfo([ 
 'geo_target_constant' => ResourceNames::forGeoTargetConstant(1022762) 
 ]), 
 'negative' => true 
 ]) 
 ]) 
 ]); 
 // Sets the LANGUAGE campaign criterion. 
 $operations[] = new MutateOperation([ 
 'campaign_criterion_operation' => new CampaignCriterionOperation([ 
 'create' => new CampaignCriterion([ 
 'campaign' => ResourceNames::forCampaign( 
 $customerId, 
 self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ), 
 // Set the language. 
 // For a list of all language codes, see: 
 // https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 
 'language' => new LanguageInfo([ 
 'language_constant' => ResourceNames::forLanguageConstant(1000)  // English 
 ]) 
 ]) 
 ]) 
 ]); 
 return $operations; 
 } 
 /** 
 * Creates multiple text assets and returns the list of resource names. 
 * 
 * @param GoogleAdsClient $googleAdsClient the Google Ads API client 
 * @param int $customerId the customer ID 
 * @param string[] $texts a list of strings, each of which will be used to create a text asset 
 * @return string[] a list of asset resource names 
 */ 
 private static function createMultipleTextAssets( 
 GoogleAdsClient $googleAdsClient, 
 int $customerId, 
 array $texts 
 ): array { 
 // Here again, we use the GoogleAdService to create multiple text assets in a single 
 // request. 
 $operations = []; 
 foreach ($texts as $text) { 
 // Creates a mutate operation for a text asset. 
 $operations[] = new MutateOperation([ 
 'asset_operation' => new AssetOperation([ 
 'create' => new Asset(['text_asset' => new TextAsset(['text' => $text])]) 
 ]) 
 ]); 
 } 
 // Issues a mutate request to add all assets. 
 $googleAdsService = $googleAdsClient->getGoogleAdsServiceClient(); 
 /** @var MutateGoogleAdsResponse $mutateGoogleAdsResponse */ 
 $mutateGoogleAdsResponse = 
 $googleAdsService->mutate(MutateGoogleAdsRequest::build($customerId, $operations)); 
 $assetResourceNames = []; 
 foreach ($mutateGoogleAdsResponse->getMutateOperationResponses() as $response) { 
 /** @var MutateOperationResponse $response */ 
 $assetResourceNames[] = $response->getAssetResult()->getResourceName(); 
 } 
 self::printResponseDetails($mutateGoogleAdsResponse); 
 return $assetResourceNames; 
 } 
 /** 
 * Creates a list of MutateOperations that create a new asset group. 
 * 
 * A temporary ID will be assigned to this asset group so that it can 
 * be referenced by other objects being created in the same Mutate request. 
 * 
 * @param int $customerId the customer ID 
 * @param string[] $headlineAssetResourceNames a list of headline resource names 
 * @param string[] $descriptionAssetResourceNames a list of description resource names 
 * @param bool $brandGuidelinesEnabled whether the created campaign will be enabled for brand 
 *     guidelines 
 * @return MutateOperation[] a list of MutateOperations that create new asset group 
 */ 
 private static function createAssetGroupOperations( 
 int $customerId, 
 array $headlineAssetResourceNames, 
 array $descriptionAssetResourceNames, 
 bool $brandGuidelinesEnabled 
 ): array { 
 $operations = []; 
 // Creates a new mutate operation that creates an asset group operation. 
 $operations[] = new MutateOperation([ 
 'asset_group_operation' => new AssetGroupOperation([ 
 'create' => new AssetGroup([ 
 'resource_name' => ResourceNames::forAssetGroup( 
 $customerId, 
 self::ASSET_GROUP_TEMPORARY_ID 
 ), 
 'name' => 'Performance Max asset group #' . Helper::getPrintableDatetime(), 
 'campaign' => ResourceNames::forCampaign( 
 $customerId, 
 self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ), 
 'final_urls' => ['http://www.example.com'], 
 'final_mobile_urls' => ['http://www.example.com'], 
 'status' => AssetGroupStatus::PAUSED 
 ]) 
 ]) 
 ]); 
 // For the list of required assets for a Performance Max campaign, see 
 // https://developers.google.com/google-ads/api/docs/performance-max/assets 
 // An AssetGroup is linked to an Asset by creating a new AssetGroupAsset 
 // and providing: 
 // -  the resource name of the AssetGroup 
 // -  the resource name of the Asset 
 // -  the field_type of the Asset in this AssetGroup 
 // 
 // To learn more about AssetGroups, see 
 // https://developers.google.com/google-ads/api/docs/performance-max/asset-groups. 
 // Links the previously created multiple text assets. 
 // Links the headline assets. 
 foreach ($headlineAssetResourceNames as $resourceName) { 
 $operations[] = new MutateOperation([ 
 'asset_group_asset_operation' => new AssetGroupAssetOperation([ 
 'create' => new AssetGroupAsset([ 
 'asset' => $resourceName, 
 'asset_group' => ResourceNames::forAssetGroup( 
 $customerId, 
 self::ASSET_GROUP_TEMPORARY_ID 
 ), 
 'field_type' => AssetFieldType::HEADLINE 
 ]) 
 ]) 
 ]); 
 } 
 // Links the description assets. 
 foreach ($descriptionAssetResourceNames as $resourceName) { 
 $operations[] = new MutateOperation([ 
 'asset_group_asset_operation' => new AssetGroupAssetOperation([ 
 'create' => new AssetGroupAsset([ 
 'asset' => $resourceName, 
 'asset_group' => ResourceNames::forAssetGroup( 
 $customerId, 
 self::ASSET_GROUP_TEMPORARY_ID 
 ), 
 'field_type' => AssetFieldType::DESCRIPTION 
 ]) 
 ]) 
 ]); 
 } 
 // Creates and links the long headline text asset. 
 $operations = array_merge($operations, self::createAndLinkTextAsset( 
 $customerId, 
 'Travel the World', 
 AssetFieldType::LONG_HEADLINE 
 )); 
 // Creates and links the business name text asset. 
 $operations = array_merge($operations, self::createAndLinkBrandAssets( 
 $customerId, 
 $brandGuidelinesEnabled, 
 'Interplanetary Cruises', 
 'https://gaagl.page.link/bjYi', 
 'Marketing Logo' 
 )); 
 // Creates and links the image assets. 
 // Creates and links the Marketing Image Asset. 
 $operations = array_merge($operations, self::createAndLinkImageAsset( 
 $customerId, 
 'https://gaagl.page.link/Eit5', 
 AssetFieldType::MARKETING_IMAGE, 
 'Marketing Image' 
 )); 
 // Creates and links the Square Marketing Image Asset. 
 $operations = array_merge($operations, self::createAndLinkImageAsset( 
 $customerId, 
 'https://gaagl.page.link/bjYi', 
 AssetFieldType::SQUARE_MARKETING_IMAGE, 
 'Square Marketing Image' 
 )); 
 return $operations; 
 } 
 /** 
 * Creates a list of MutateOperations that create a new linked text asset. 
 * 
 * @param int $customerId the customer ID 
 * @param string $text the text of the asset to be created 
 * @param int $fieldType the field type of the new asset in the AssetGroupAsset 
 * @return MutateOperation[] a list of MutateOperations that create a new linked text asset 
 */ 
 private static function createAndLinkTextAsset( 
 int $customerId, 
 string $text, 
 int $fieldType 
 ): array { 
 $operations = []; 
 // Creates a new mutate operation that creates a text asset. 
 $operations[] = new MutateOperation([ 
 'asset_operation' => new AssetOperation([ 
 'create' => new Asset([ 
 'resource_name' => ResourceNames::forAsset($customerId, self::$nextTempId), 
 'text_asset' => new TextAsset(['text' => $text]) 
 ]) 
 ]) 
 ]); 
 // Creates an asset group asset to link the asset to the asset group. 
 $operations[] = new MutateOperation([ 
 'asset_group_asset_operation' => new AssetGroupAssetOperation([ 
 'create' => new AssetGroupAsset([ 
 'asset' => ResourceNames::forAsset($customerId, self::$nextTempId), 
 'asset_group' => ResourceNames::forAssetGroup( 
 $customerId, 
 self::ASSET_GROUP_TEMPORARY_ID 
 ), 
 'field_type' => $fieldType 
 ]) 
 ]) 
 ]); 
 self::$nextTempId--; 
 return $operations; 
 } 
 /** 
 * Creates a list of MutateOperations that create a new linked image asset. 
 * 
 * @param int $customerId the customer ID 
 * @param string $url the URL of the image to be retrieved and put into an asset 
 * @param int $fieldType the field type of the new asset in the AssetGroupAsset 
 * @param string $assetName the asset name 
 * @return MutateOperation[] a list of MutateOperations that create a new linked image asset 
 */ 
 private static function createAndLinkImageAsset( 
 int $customerId, 
 string $url, 
 int $fieldType, 
 string $assetName 
 ): array { 
 $operations = []; 
 // Creates a new mutate operation that creates an image asset. 
 $operations[] = new MutateOperation([ 
 'asset_operation' => new AssetOperation([ 
 'create' => new Asset([ 
 'resource_name' => ResourceNames::forAsset($customerId, self::$nextTempId), 
 // Provide a unique friendly name to identify your asset. 
 // When there is an existing image asset with the same content but a different 
 // name, the new name will be dropped silently. 
 'name' => $assetName, 
 'image_asset' => new ImageAsset(['data' => file_get_contents($url)]) 
 ]) 
 ]) 
 ]); 
 // Creates an asset group asset to link the asset to the asset group. 
 $operations[] = new MutateOperation([ 
 'asset_group_asset_operation' => new AssetGroupAssetOperation([ 
 'create' => new AssetGroupAsset([ 
 'asset' => ResourceNames::forAsset($customerId, self::$nextTempId), 
 'asset_group' => ResourceNames::forAssetGroup( 
 $customerId, 
 self::ASSET_GROUP_TEMPORARY_ID 
 ), 
 'field_type' => $fieldType 
 ]) 
 ]) 
 ]); 
 self::$nextTempId--; 
 return $operations; 
 } 
 /** 
 * Creates a list of MutateOperations that create linked brand assets. 
 * 
 * @param int $customerId the customer ID 
 * @param bool $brandGuidelinesEnabled whether the created campaign will be enabled for brand 
 *     guidelines 
 * @param string $businessName the business name text to be put into an asset 
 * @param string $logoUrl the URL of the logo to be retrieved and put into an asset 
 * @param string $logoName the asset name of the logo 
 * @return MutateOperation[] a list of MutateOperations that create a new linked text asset 
 */ 
 private static function createAndLinkBrandAssets( 
 int $customerId, 
 bool $brandGuidelinesEnabled, 
 string $businessName, 
 string $logoUrl, 
 string $logoName 
 ): array { 
 $operations = []; 
 // Creates a new mutate operation that creates a text asset. 
 $businessNameTempId = self::$nextTempId--; 
 $operations[] = new MutateOperation([ 
 'asset_operation' => new AssetOperation([ 
 'create' => new Asset([ 
 'resource_name' => ResourceNames::forAsset($customerId, $businessNameTempId), 
 'text_asset' => new TextAsset(['text' => $businessName]) 
 ]) 
 ]) 
 ]); 
 $logoTempId = self::$nextTempId--; 
 // Creates a new mutate operation that creates an image asset. 
 $operations[] = new MutateOperation([ 
 'asset_operation' => new AssetOperation([ 
 'create' => new Asset([ 
 'resource_name' => ResourceNames::forAsset($customerId, $logoTempId), 
 // Provide a unique friendly name to identify your asset. 
 // When there is an existing image asset with the same content but a different 
 // name, the new name will be dropped silently. 
 'name' => $logoName, 
 'image_asset' => new ImageAsset(['data' => file_get_contents($logoUrl)]) 
 ]) 
 ]) 
 ]); 
 if ($brandGuidelinesEnabled) { 
 // Creates a campaign asset to link the business name and logo assets to the campaign. 
 $operations[] = new MutateOperation([ 
 'campaign_asset_operation' => new CampaignAssetOperation([ 
 'create' => new CampaignAsset([ 
 'asset' => ResourceNames::forAsset($customerId, $businessNameTempId), 
 'campaign' => ResourceNames::forCampaign( 
 $customerId, 
 self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ), 
 'field_type' => AssetFieldType::BUSINESS_NAME 
 ]) 
 ]) 
 ]); 
 $operations[] = new MutateOperation([ 
 'campaign_asset_operation' => new CampaignAssetOperation([ 
 'create' => new CampaignAsset([ 
 'asset' => ResourceNames::forAsset($customerId, $logoTempId), 
 'campaign' => ResourceNames::forCampaign( 
 $customerId, 
 self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ), 
 'field_type' => AssetFieldType::LOGO 
 ]) 
 ]) 
 ]); 
 } else { 
 // Creates an asset group asset to link the business name and logo assets to the asset 
 // group. 
 $operations[] = new MutateOperation([ 
 'asset_group_asset_operation' => new AssetGroupAssetOperation([ 
 'create' => new AssetGroupAsset([ 
 'asset' => ResourceNames::forAsset($customerId, $businessNameTempId), 
 'asset_group' => ResourceNames::forAssetGroup( 
 $customerId, 
 self::ASSET_GROUP_TEMPORARY_ID 
 ), 
 'field_type' => AssetFieldType::BUSINESS_NAME 
 ]) 
 ]) 
 ]); 
 $operations[] = new MutateOperation([ 
 'asset_group_asset_operation' => new AssetGroupAssetOperation([ 
 'create' => new AssetGroupAsset([ 
 'asset' => ResourceNames::forAsset($customerId, $logoTempId), 
 'asset_group' => ResourceNames::forAssetGroup( 
 $customerId, 
 self::ASSET_GROUP_TEMPORARY_ID 
 ), 
 'field_type' => AssetFieldType::LOGO 
 ]) 
 ]) 
 ]); 
 } 
 return $operations; 
 } 
 /** 
 * Creates a list of MutateOperations that may create asset group signals. 
 * 
 * @param int $customerId the customer ID 
 * @param string $assetGroupResourceName the resource name of the asset group 
 * @param int|null $audienceId the audience ID 
 * @return MutateOperation[] a list of MutateOperations that may create asset group signals 
 */ 
 private static function createAssetGroupSignalOperations( 
 int $customerId, 
 string $assetGroupResourceName, 
 ?int $audienceId 
 ): array { 
 $operations = []; 
 if (is_null($audienceId)) { 
 return $operations; 
 } 
 $operations[] = new MutateOperation([ 
 'asset_group_signal_operation' => new AssetGroupSignalOperation([ 
 // To learn more about Audience Signals, see 
 // https://developers.google.com/google-ads/api/docs/performance-max/asset-groups#audience_signals. 
 'create' => new AssetGroupSignal([ 
 'asset_group' => $assetGroupResourceName, 
 'audience' => new AudienceInfo([ 
 'audience' => ResourceNames::forAudience($customerId, $audienceId) 
 ]) 
 ]) 
 ]) 
 ]); 
 return $operations; 
 } 
 /** 
 * 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. 
 * 
 * @param MutateGoogleAdsResponse $mutateGoogleAdsResponse the mutate Google Ads response 
 */ 
 private static function printResponseDetails( 
 MutateGoogleAdsResponse $mutateGoogleAdsResponse 
 ): void { 
 foreach ($mutateGoogleAdsResponse->getMutateOperationResponses() as $response) { 
 /** @var MutateOperationResponse $response */ 
 $getter = Serializer::getGetter($response->getResponse()); 
 printf( 
 "Created a(n) %s with '%s'.%s", 
 preg_replace( 
 '/Result$/', 
 '', 
 ucfirst(Serializer::toCamelCase($response->getResponse())) 
 ), 
 $response->$getter()->getResourceName(), 
 PHP_EOL 
 ); 
 } 
 } 
 } 
 AddPerformanceMaxCampaign::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 Performance Max campaign. 
 For more information about Performance Max campaigns, see 
 https://developers.google.com/google-ads/api/docs/performance-max/overview 
 Prerequisites: 
 - You must have at least one conversion action in the account. For 
 more about conversion actions, see 
 https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions 
 This example uses the default customer conversion goals. For an example 
 of setting campaign-specific conversion goals, see 
 shopping_ads/add_performance_max_retail_campaign.py 
 """ 
 import 
  
 argparse 
 from 
  
 datetime 
  
 import 
 datetime 
 , 
 timedelta 
 import 
  
 sys 
 from 
  
 typing 
  
 import 
 List 
 , 
 Optional 
 , 
 Iterable 
 from 
  
 uuid 
  
 import 
 uuid4 
 from 
  
 examples.utils.example_helpers 
  
 import 
 get_image_bytes_from_url 
 from 
  
 google.ads.googleads.client 
  
 import 
 GoogleAdsClient 
 from 
  
 google.ads.googleads.errors 
  
 import 
 GoogleAdsException 
 from 
  
 google.ads.googleads.util 
  
 import 
 convert_snake_case_to_upper_case 
 from 
  
 google.ads.googleads.v21.enums.types.asset_field_type 
  
 import 
 ( 
 AssetFieldTypeEnum 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.resources.types.asset 
  
 import 
 Asset 
 from 
  
 google.ads.googleads.v21.resources.types.asset_group 
  
 import 
 AssetGroup 
 from 
  
 google.ads.googleads.v21.resources.types.asset_group_asset 
  
 import 
 ( 
 AssetGroupAsset 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.resources.types.asset_group_signal 
  
 import 
 ( 
 AssetGroupSignal 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.resources.types.campaign 
  
 import 
 Campaign 
 from 
  
 google.ads.googleads.v21.resources.types.campaign_asset 
  
 import 
 ( 
 CampaignAsset 
 , 
 ) 
 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.services.services.asset_group_service 
  
 import 
 ( 
 AssetGroupServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.services.asset_service 
  
 import 
 ( 
 AssetServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.services.campaign_service 
  
 import 
 ( 
 CampaignServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.services.geo_target_constant_service 
  
 import 
 ( 
 GeoTargetConstantServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.services.google_ads_service 
  
 import 
 ( 
 GoogleAdsServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.campaign_budget_service 
  
 import 
 ( 
 CampaignBudgetOperation 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.google_ads_service 
  
 import 
 ( 
 MutateGoogleAdsResponse 
 , 
 MutateOperation 
 , 
 MutateOperationResponse 
 , 
 ) 
 # We specify temporary IDs that are specific to a single mutate request. 
 # Temporary IDs are always negative and unique within one mutate request. 
 # 
 # See https://developers.google.com/google-ads/api/docs/mutating/best-practices 
 # for further details. 
 # 
 # These temporary IDs are fixed because they are used in multiple places. 
 _BUDGET_TEMPORARY_ID 
 = 
 "-1" 
 _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 = 
 "-2" 
 _ASSET_GROUP_TEMPORARY_ID 
 = 
 "-3" 
 # There are also entities that will be created in the same request but do not 
 # need to be fixed temporary IDs because they are referenced only once. 
 next_temp_id 
 = 
 int 
 ( 
 _ASSET_GROUP_TEMPORARY_ID 
 ) 
 - 
 1 
 def 
  
 main 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 audience_id 
 : 
 Optional 
 [ 
 str 
 ], 
 brand_guidelines_enabled 
 : 
 bool 
 , 
 ) 
 - 
> None 
 : 
  
 """The main method that creates all necessary entities for the example. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 audience_id: an optional audience ID. 
 brand_guidelines_enabled: a boolean value indicating if the campaign is 
 enabled for brand guidelines. 
 """ 
 googleads_service 
 : 
 GoogleAdsServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "GoogleAdsService" 
 ) 
 # Performance Max campaigns require that repeated assets such as headlines 
 # and descriptions be created before the campaign. 
 # For the list of required assets for a Performance Max campaign, see 
 # https://developers.google.com/google-ads/api/docs/performance-max/assets 
 # 
 # Create the headlines. 
 headline_asset_resource_names 
 : 
 List 
 [ 
 str 
 ] 
 = 
 create_multiple_text_assets 
 ( 
 client 
 , 
 customer_id 
 , 
 [ 
 "Travel" 
 , 
 "Travel Reviews" 
 , 
 "Book travel" 
 , 
 ], 
 ) 
 # Create the descriptions. 
 description_asset_resource_names 
 : 
 List 
 [ 
 str 
 ] 
 = 
 create_multiple_text_assets 
 ( 
 client 
 , 
 customer_id 
 , 
 [ 
 "Take to the air!" 
 , 
 "Fly to the sky!" 
 , 
 ], 
 ) 
 # 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 Performance Max 
 # 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 
 , 
 ) 
 ) 
 performance_max_campaign_operation 
 : 
 MutateOperation 
 = 
 ( 
 create_performance_max_campaign_operation 
 ( 
 client 
 , 
 customer_id 
 , 
 brand_guidelines_enabled 
 , 
 ) 
 ) 
 campaign_criterion_operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 ( 
 create_campaign_criterion_operations 
 ( 
 client 
 , 
 customer_id 
 , 
 ) 
 ) 
 asset_group_operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 ( 
 create_asset_group_operation 
 ( 
 client 
 , 
 customer_id 
 , 
 headline_asset_resource_names 
 , 
 description_asset_resource_names 
 , 
 brand_guidelines_enabled 
 , 
 ) 
 ) 
 asset_group_signal_operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 ( 
 create_asset_group_signal_operations 
 ( 
 client 
 , 
 customer_id 
 , 
 audience_id 
 ) 
 ) 
 mutate_operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 [ 
 # It's important to create these entities in this order because 
 # they depend on each other. 
 campaign_budget_operation 
 , 
 performance_max_campaign_operation 
 , 
 # Expand the list of multiple operations into the list of 
 # other mutate operations 
 * 
 campaign_criterion_operations 
 , 
 * 
 asset_group_operations 
 , 
 * 
 asset_group_signal_operations 
 , 
 ] 
 # Send the operations in a single Mutate request. 
 response 
 : 
 MutateGoogleAdsResponse 
 = 
 googleads_service 
 . 
 mutate 
 ( 
 customer_id 
 = 
 customer_id 
 , 
 mutate_operations 
 = 
 mutate_operations 
 ) 
 print_response_details 
 ( 
 response 
 ) 
 def 
  
 create_campaign_budget_operation 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 ) 
 - 
> 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. 
 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 
 "Performance Max campaign budget # 
 { 
 uuid4 
 () 
 } 
 " 
 # The budget period already defaults to DAILY. 
 campaign_budget 
 . 
 amount_micros 
 = 
 50000000 
 campaign_budget 
 . 
 delivery_method 
 = 
 ( 
 client 
 . 
 enums 
 . 
 BudgetDeliveryMethodEnum 
 . 
 STANDARD 
 ) 
 # A Performance Max campaign cannot use a shared campaign budget. 
 campaign_budget 
 . 
 explicitly_shared 
 = 
 False 
 # 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_performance_max_campaign_operation 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 brand_guidelines_enabled 
 : 
 bool 
 , 
 ) 
 - 
> MutateOperation 
 : 
  
 """Creates a MutateOperation that creates a new Performance Max 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. 
 brand_guidelines_enabled: a boolean value indicating if the campaign is 
 enabled for brand guidelines. 
 Returns: 
 a MutateOperation that creates a campaign. 
 """ 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 campaign 
 : 
 Campaign 
 = 
 mutate_operation 
 . 
 campaign_operation 
 . 
 create 
 campaign 
 . 
 name 
 = 
 f 
 "Performance Max 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 
 # All Performance Max campaigns have an advertising_channel_type of 
 # PERFORMANCE_MAX. The advertising_channel_sub_type should not be set. 
 campaign 
 . 
 advertising_channel_type 
 = 
 ( 
 client 
 . 
 enums 
 . 
 AdvertisingChannelTypeEnum 
 . 
 PERFORMANCE_MAX 
 ) 
 # Bidding strategy must be set directly on the campaign. 
 # Setting a portfolio bidding strategy by resource name is not supported. 
 # Max Conversion and Maximize Conversion Value are the only strategies 
 # supported for Performance Max campaigns. 
 # An optional ROAS (Return on Advertising Spend) can be set for 
 # maximize_conversion_value. The ROAS value must be specified as a ratio in 
 # the API. It is calculated by dividing "total value" by "total spend". 
 # For more information on Maximize Conversion Value, see the support 
 # article: http://support.google.com/google-ads/answer/7684216. 
 # A target_roas of 3.5 corresponds to a 350% return on ad spend. 
 campaign 
 . 
 bidding_strategy_type 
 = 
 ( 
 client 
 . 
 enums 
 . 
 BiddingStrategyTypeEnum 
 . 
 MAXIMIZE_CONVERSION_VALUE 
 ) 
 campaign 
 . 
 maximize_conversion_value 
 . 
 target_roas 
 = 
 3.5 
 # Set the Final URL expansion opt out. This flag is specific to 
 # Performance Max campaigns. If opted out (True), only the final URLs in 
 # the asset group or URLs specified in the advertiser's Google Merchant 
 # Center or business data feeds are targeted. 
 # If opted in (False), the entire domain will be targeted. For best 
 # results, set this value to false to opt in and allow URL expansions. You 
 # can optionally add exclusions to limit traffic to parts of your website. 
 campaign 
 . 
 url_expansion_opt_out 
 = 
 False 
 # Set if the campaign is enabled for brand guidelines. For more information 
 # on brand guidelines, see https://support.google.com/google-ads/answer/14934472. 
 campaign 
 . 
 brand_guidelines_enabled 
 = 
 brand_guidelines_enabled 
 # Assign the resource name with a temporary ID. 
 campaign_service 
 : 
 CampaignServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "CampaignService" 
 ) 
 campaign 
 . 
 resource_name 
 = 
 campaign_service 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
 # Set the budget using the given budget resource name. 
 campaign 
 . 
 campaign_budget 
 = 
 campaign_service 
 . 
 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 
 ) 
 # Optional fields 
 campaign 
 . 
 start_date 
 = 
 ( 
 datetime 
 . 
 now 
 () 
 + 
 timedelta 
 ( 
 1 
 )) 
 . 
 strftime 
 ( 
 "%Y%m 
 %d 
 " 
 ) 
 campaign 
 . 
 end_date 
 = 
 ( 
 datetime 
 . 
 now 
 () 
 + 
 timedelta 
 ( 
 365 
 )) 
 . 
 strftime 
 ( 
 "%Y%m 
 %d 
 " 
 ) 
 return 
 mutate_operation 
 def 
  
 create_campaign_criterion_operations 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 ) 
 - 
> List 
 [ 
 MutateOperation 
 ]: 
  
 """Creates a list of MutateOperations that create new campaign criteria. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 Returns: 
 a list of MutateOperations that create new campaign criteria. 
 """ 
 campaign_service 
 : 
 CampaignServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "CampaignService" 
 ) 
 geo_target_constant_service 
 : 
 GeoTargetConstantServiceClient 
 = 
 ( 
 client 
 . 
 get_service 
 ( 
 "GeoTargetConstantService" 
 ) 
 ) 
 googleads_service 
 : 
 GoogleAdsServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "GoogleAdsService" 
 ) 
 operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 [] 
 # Set the LOCATION campaign criteria. 
 # Target all of New York City except Brooklyn. 
 # Location IDs are listed here: 
 # https://developers.google.com/google-ads/api/reference/data/geotargets 
 # and they can also be retrieved using the GeoTargetConstantService as shown 
 # here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting 
 # 
 # We will add one positive location target for New York City (ID=1023191) 
 # and one negative location target for Brooklyn (ID=1022762). 
 # First, add the positive (negative = False) for New York City. 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 campaign_criterion 
 : 
 CampaignCriterion 
 = 
 ( 
 mutate_operation 
 . 
 campaign_criterion_operation 
 . 
 create 
 ) 
 campaign_criterion 
 . 
 campaign 
 = 
 campaign_service 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
 campaign_criterion 
 . 
 location 
 . 
 geo_target_constant 
 = 
 ( 
 geo_target_constant_service 
 . 
 geo_target_constant_path 
 ( 
 "1023191" 
 ) 
 ) 
 campaign_criterion 
 . 
 negative 
 = 
 False 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 # Next add the negative target for Brooklyn. 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 campaign_criterion 
 : 
 CampaignCriterion 
 = 
 ( 
 mutate_operation 
 . 
 campaign_criterion_operation 
 . 
 create 
 ) 
 campaign_criterion 
 . 
 campaign 
 = 
 campaign_service 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
 campaign_criterion 
 . 
 location 
 . 
 geo_target_constant 
 = 
 ( 
 geo_target_constant_service 
 . 
 geo_target_constant_path 
 ( 
 "1022762" 
 ) 
 ) 
 campaign_criterion 
 . 
 negative 
 = 
 True 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 # Set the LANGUAGE campaign criterion. 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 campaign_criterion 
 : 
 CampaignCriterion 
 = 
 ( 
 mutate_operation 
 . 
 campaign_criterion_operation 
 . 
 create 
 ) 
 campaign_criterion 
 . 
 campaign 
 = 
 campaign_service 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
 # Set the language. 
 # For a list of all language codes, see: 
 # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 
 campaign_criterion 
 . 
 language 
 . 
 language_constant 
 = 
 ( 
 googleads_service 
 . 
 language_constant_path 
 ( 
 "1000" 
 ) 
 ) 
 # English 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 return 
 operations 
 def 
  
 create_multiple_text_assets 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 texts 
 : 
 List 
 [ 
 str 
 ] 
 ) 
 - 
> List 
 [ 
 str 
 ]: 
  
 """Creates multiple text assets and returns the list of resource names. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 texts: a list of strings, each of which will be used to create a text 
 asset. 
 Returns: 
 asset_resource_names: a list of asset resource names. 
 """ 
 # Here again we use the GoogleAdService to create multiple text 
 # assets in a single request. 
 googleads_service 
 : 
 GoogleAdsServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "GoogleAdsService" 
 ) 
 operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 [] 
 for 
 text 
 in 
 texts 
 : 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 asset 
 : 
 Asset 
 = 
 mutate_operation 
 . 
 asset_operation 
 . 
 create 
 asset 
 . 
 text_asset 
 . 
 text 
 = 
 text 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 # Send the operations in a single Mutate request. 
 response 
 : 
 MutateGoogleAdsResponse 
 = 
 googleads_service 
 . 
 mutate 
 ( 
 customer_id 
 = 
 customer_id 
 , 
 mutate_operations 
 = 
 operations 
 , 
 ) 
 asset_resource_names 
 : 
 List 
 [ 
 str 
 ] 
 = 
 [] 
 for 
 result 
 in 
 response 
 . 
 mutate_operation_responses 
 : 
 if 
 result 
 . 
 _pb 
 . 
 HasField 
 ( 
 "asset_result" 
 ): 
 asset_resource_names 
 . 
 append 
 ( 
 result 
 . 
 asset_result 
 . 
 resource_name 
 ) 
 print_response_details 
 ( 
 response 
 ) 
 return 
 asset_resource_names 
 def 
  
 create_asset_group_operation 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 headline_asset_resource_names 
 : 
 List 
 [ 
 str 
 ], 
 description_asset_resource_names 
 : 
 List 
 [ 
 str 
 ], 
 brand_guidelines_enabled 
 : 
 bool 
 , 
 ) 
 - 
> List 
 [ 
 MutateOperation 
 ]: 
  
 """Creates a list of MutateOperations that create a new asset_group. 
 A temporary ID will be assigned to this asset group 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. 
 headline_asset_resource_names: a list of headline resource names. 
 description_asset_resource_names: a list of description resource names. 
 brand_guidelines_enabled: a boolean value indicating if the campaign is 
 enabled for brand guidelines. 
 Returns: 
 MutateOperations that create a new asset group and related assets. 
 """ 
 asset_group_service 
 : 
 AssetGroupServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "AssetGroupService" 
 ) 
 campaign_service 
 : 
 CampaignServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "CampaignService" 
 ) 
 operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 [] 
 # Create the AssetGroup 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 asset_group 
 : 
 AssetGroup 
 = 
 mutate_operation 
 . 
 asset_group_operation 
 . 
 create 
 asset_group 
 . 
 name 
 = 
 f 
 "Performance Max asset group # 
 { 
 uuid4 
 () 
 } 
 " 
 asset_group 
 . 
 campaign 
 = 
 campaign_service 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
 asset_group 
 . 
 final_urls 
 . 
 append 
 ( 
 "http://www.example.com" 
 ) 
 asset_group 
 . 
 final_mobile_urls 
 . 
 append 
 ( 
 "http://www.example.com" 
 ) 
 asset_group 
 . 
 status 
 = 
 client 
 . 
 enums 
 . 
 AssetGroupStatusEnum 
 . 
 PAUSED 
 asset_group 
 . 
 resource_name 
 = 
 asset_group_service 
 . 
 asset_group_path 
 ( 
 customer_id 
 , 
 _ASSET_GROUP_TEMPORARY_ID 
 , 
 ) 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 # For the list of required assets for a Performance Max campaign, see 
 # https://developers.google.com/google-ads/api/docs/performance-max/assets 
 # An AssetGroup is linked to an Asset by creating a new AssetGroupAsset 
 # and providing: 
 #   the resource name of the AssetGroup 
 #   the resource name of the Asset 
 #   the field_type of the Asset in this AssetGroup. 
 # 
 # To learn more about AssetGroups, see 
 # https://developers.google.com/google-ads/api/docs/performance-max/asset-groups 
 # Link the previously created multiple text assets. 
 # Link the headline assets. 
 for 
 resource_name 
 in 
 headline_asset_resource_names 
 : 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 asset_group_asset 
 : 
 AssetGroupAsset 
 = 
 ( 
 mutate_operation 
 . 
 asset_group_asset_operation 
 . 
 create 
 ) 
 asset_group_asset 
 . 
 field_type 
 = 
 client 
 . 
 enums 
 . 
 AssetFieldTypeEnum 
 . 
 HEADLINE 
 asset_group_asset 
 . 
 asset_group 
 = 
 asset_group_service 
 . 
 asset_group_path 
 ( 
 customer_id 
 , 
 _ASSET_GROUP_TEMPORARY_ID 
 , 
 ) 
 asset_group_asset 
 . 
 asset 
 = 
 resource_name 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 #  Link the description assets. 
 for 
 resource_name 
 in 
 description_asset_resource_names 
 : 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 asset_group_asset 
 : 
 AssetGroupAsset 
 = 
 ( 
 mutate_operation 
 . 
 asset_group_asset_operation 
 . 
 create 
 ) 
 asset_group_asset 
 . 
 field_type 
 = 
 ( 
 client 
 . 
 enums 
 . 
 AssetFieldTypeEnum 
 . 
 DESCRIPTION 
 ) 
 asset_group_asset 
 . 
 asset_group 
 = 
 asset_group_service 
 . 
 asset_group_path 
 ( 
 customer_id 
 , 
 _ASSET_GROUP_TEMPORARY_ID 
 , 
 ) 
 asset_group_asset 
 . 
 asset 
 = 
 resource_name 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 # Create and link the long headline text asset. 
 mutate_operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 create_and_link_text_asset 
 ( 
 client 
 , 
 customer_id 
 , 
 "Travel the World" 
 , 
 client 
 . 
 enums 
 . 
 AssetFieldTypeEnum 
 . 
 LONG_HEADLINE 
 , 
 ) 
 operations 
 . 
 extend 
 ( 
 mutate_operations 
 ) 
 # Create and link the business name and logo asset. 
 mutate_operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 create_and_link_brand_assets 
 ( 
 client 
 , 
 customer_id 
 , 
 brand_guidelines_enabled 
 , 
 "Interplanetary Cruises" 
 , 
 "https://gaagl.page.link/bjYi" 
 , 
 "Marketing Logo" 
 , 
 ) 
 operations 
 . 
 extend 
 ( 
 mutate_operations 
 ) 
 # Create and link the image assets. 
 # Create and link the Marketing Image Asset. 
 mutate_operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 create_and_link_image_asset 
 ( 
 client 
 , 
 customer_id 
 , 
 "https://gaagl.page.link/Eit5" 
 , 
 client 
 . 
 enums 
 . 
 AssetFieldTypeEnum 
 . 
 MARKETING_IMAGE 
 , 
 "Marketing Image" 
 , 
 ) 
 operations 
 . 
 extend 
 ( 
 mutate_operations 
 ) 
 # Create and link the Square Marketing Image Asset. 
 mutate_operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 create_and_link_image_asset 
 ( 
 client 
 , 
 customer_id 
 , 
 "https://gaagl.page.link/bjYi" 
 , 
 client 
 . 
 enums 
 . 
 AssetFieldTypeEnum 
 . 
 SQUARE_MARKETING_IMAGE 
 , 
 "Square Marketing Image" 
 , 
 ) 
 operations 
 . 
 extend 
 ( 
 mutate_operations 
 ) 
 return 
 operations 
 def 
  
 create_and_link_text_asset 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 text 
 : 
 str 
 , 
 field_type 
 : 
 AssetFieldTypeEnum 
 . 
 AssetFieldType 
 , 
 ) 
 - 
> List 
 [ 
 MutateOperation 
 ]: 
  
 """Creates a list of MutateOperations that create a new linked text asset. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 text: the text of the asset to be created. 
 field_type: the field_type of the new asset in the AssetGroupAsset. 
 Returns: 
 MutateOperations that create a new linked text asset. 
 """ 
 global 
 next_temp_id 
 operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 [] 
 asset_service 
 : 
 AssetServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "AssetService" 
 ) 
 asset_group_service 
 : 
 AssetGroupServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "AssetGroupService" 
 ) 
 # Create the Text Asset. 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 asset 
 : 
 Asset 
 = 
 mutate_operation 
 . 
 asset_operation 
 . 
 create 
 asset 
 . 
 resource_name 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 next_temp_id 
 ) 
 asset 
 . 
 text_asset 
 . 
 text 
 = 
 text 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 # Create an AssetGroupAsset to link the Asset to the AssetGroup. 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 asset_group_asset 
 : 
 AssetGroupAsset 
 = 
 ( 
 mutate_operation 
 . 
 asset_group_asset_operation 
 . 
 create 
 ) 
 asset_group_asset 
 . 
 field_type 
 = 
 field_type 
 asset_group_asset 
 . 
 asset_group 
 = 
 asset_group_service 
 . 
 asset_group_path 
 ( 
 customer_id 
 , 
 _ASSET_GROUP_TEMPORARY_ID 
 , 
 ) 
 asset_group_asset 
 . 
 asset 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 next_temp_id 
 ) 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 next_temp_id 
 -= 
 1 
 return 
 operations 
 def 
  
 create_and_link_image_asset 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 url 
 : 
 str 
 , 
 field_type 
 : 
 AssetFieldTypeEnum 
 . 
 AssetFieldType 
 , 
 asset_name 
 : 
 str 
 , 
 ) 
 - 
> List 
 [ 
 MutateOperation 
 ]: 
  
 """Creates a list of MutateOperations that create a new linked image asset. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 url: the url of the image to be retrieved and put into an asset. 
 field_type: the field_type of the new asset in the AssetGroupAsset. 
 asset_name: the asset name. 
 Returns: 
 MutateOperations that create a new linked image asset. 
 """ 
 global 
 next_temp_id 
 operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 [] 
 asset_service 
 : 
 AssetServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "AssetService" 
 ) 
 asset_group_service 
 : 
 AssetGroupServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "AssetGroupService" 
 ) 
 # Create the Image Asset. 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 asset 
 : 
 Asset 
 = 
 mutate_operation 
 . 
 asset_operation 
 . 
 create 
 asset 
 . 
 resource_name 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 next_temp_id 
 ) 
 # Provide a unique friendly name to identify your asset. 
 # When there is an existing image asset with the same content but a different 
 # name, the new name will be dropped silently. 
 asset 
 . 
 name 
 = 
 asset_name 
 asset 
 . 
 type_ 
 = 
 client 
 . 
 enums 
 . 
 AssetTypeEnum 
 . 
 IMAGE 
 asset 
 . 
 image_asset 
 . 
 data 
 = 
 get_image_bytes_from_url 
 ( 
 url 
 ) 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 # Create an AssetGroupAsset to link the Asset to the AssetGroup. 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 asset_group_asset 
 : 
 AssetGroupAsset 
 = 
 ( 
 mutate_operation 
 . 
 asset_group_asset_operation 
 . 
 create 
 ) 
 asset_group_asset 
 . 
 field_type 
 = 
 field_type 
 asset_group_asset 
 . 
 asset_group 
 = 
 asset_group_service 
 . 
 asset_group_path 
 ( 
 customer_id 
 , 
 _ASSET_GROUP_TEMPORARY_ID 
 , 
 ) 
 asset_group_asset 
 . 
 asset 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 next_temp_id 
 ) 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 next_temp_id 
 -= 
 1 
 return 
 operations 
 def 
  
 create_and_link_brand_assets 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 brand_guidelines_enabled 
 : 
 bool 
 , 
 business_name 
 : 
 str 
 , 
 logo_url 
 : 
 str 
 , 
 logo_name 
 : 
 str 
 , 
 ) 
 - 
> List 
 [ 
 MutateOperation 
 ]: 
  
 """Creates a list of MutateOperations that create linked brand assets. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 brand_guidelines_enabled: a boolean value indicating if the campaign is 
 enabled for brand guidelines. 
 business_name: the business name text to be put into an asset. 
 logo_url: the url of the logo to be retrieved and put into an asset. 
 logo_name: the asset name of the logo. 
 Returns: 
 MutateOperations that create linked brand assets. 
 """ 
 global 
 next_temp_id 
 operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 [] 
 asset_service 
 : 
 AssetServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "AssetService" 
 ) 
 # Create the Text Asset. 
 text_asset_temp_id 
 = 
 next_temp_id 
 next_temp_id 
 -= 
 1 
 text_mutate_operation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 text_asset 
 : 
 Asset 
 = 
 text_mutate_operation 
 . 
 asset_operation 
 . 
 create 
 text_asset 
 . 
 resource_name 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 text_asset_temp_id 
 ) 
 text_asset 
 . 
 text_asset 
 . 
 text 
 = 
 business_name 
 operations 
 . 
 append 
 ( 
 text_mutate_operation 
 ) 
 # Create the Image Asset. 
 image_asset_temp_id 
 = 
 next_temp_id 
 next_temp_id 
 -= 
 1 
 image_mutate_operation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 image_asset 
 : 
 Asset 
 = 
 image_mutate_operation 
 . 
 asset_operation 
 . 
 create 
 image_asset 
 . 
 resource_name 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 image_asset_temp_id 
 ) 
 # Provide a unique friendly name to identify your asset. 
 # When there is an existing image asset with the same content but a different 
 # name, the new name will be dropped silently. 
 image_asset 
 . 
 name 
 = 
 logo_name 
 image_asset 
 . 
 type_ 
 = 
 client 
 . 
 enums 
 . 
 AssetTypeEnum 
 . 
 IMAGE 
 image_asset 
 . 
 image_asset 
 . 
 data 
 = 
 get_image_bytes_from_url 
 ( 
 logo_url 
 ) 
 operations 
 . 
 append 
 ( 
 image_mutate_operation 
 ) 
 if 
 brand_guidelines_enabled 
 : 
 # Create CampaignAsset resources to link the Asset resources to the Campaign. 
 campaign_service 
 : 
 CampaignServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "CampaignService" 
 ) 
 business_name_mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 business_name_campaign_asset 
 : 
 CampaignAsset 
 = 
 ( 
 business_name_mutate_operation 
 . 
 campaign_asset_operation 
 . 
 create 
 ) 
 business_name_campaign_asset 
 . 
 field_type 
 = 
 ( 
 client 
 . 
 enums 
 . 
 AssetFieldTypeEnum 
 . 
 BUSINESS_NAME 
 ) 
 business_name_campaign_asset 
 . 
 campaign 
 = 
 campaign_service 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
 business_name_campaign_asset 
 . 
 asset 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 text_asset_temp_id 
 ) 
 operations 
 . 
 append 
 ( 
 business_name_mutate_operation 
 ) 
 logo_mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 logo_campaign_asset 
 : 
 CampaignAsset 
 = 
 ( 
 logo_mutate_operation 
 . 
 campaign_asset_operation 
 . 
 create 
 ) 
 logo_campaign_asset 
 . 
 field_type 
 = 
 client 
 . 
 enums 
 . 
 AssetFieldTypeEnum 
 . 
 LOGO 
 logo_campaign_asset 
 . 
 campaign 
 = 
 campaign_service 
 . 
 campaign_path 
 ( 
 customer_id 
 , 
 _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
 logo_campaign_asset 
 . 
 asset 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 image_asset_temp_id 
 ) 
 operations 
 . 
 append 
 ( 
 logo_mutate_operation 
 ) 
 else 
 : 
 # Create AssetGroupAsset resources to link the Asset resources to the AssetGroup. 
 asset_group_service 
 : 
 AssetGroupServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "AssetGroupService" 
 ) 
 business_name_mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 business_name_asset_group_asset 
 : 
 AssetGroupAsset 
 = 
 ( 
 business_name_mutate_operation 
 . 
 asset_group_asset_operation 
 . 
 create 
 ) 
 business_name_asset_group_asset 
 . 
 field_type 
 = 
 ( 
 client 
 . 
 enums 
 . 
 AssetFieldTypeEnum 
 . 
 BUSINESS_NAME 
 ) 
 business_name_asset_group_asset 
 . 
 asset_group 
 = 
 ( 
 asset_group_service 
 . 
 asset_group_path 
 ( 
 customer_id 
 , 
 _ASSET_GROUP_TEMPORARY_ID 
 , 
 ) 
 ) 
 business_name_asset_group_asset 
 . 
 asset 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 text_asset_temp_id 
 ) 
 operations 
 . 
 append 
 ( 
 business_name_mutate_operation 
 ) 
 logo_mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 logo_asset_group_asset 
 : 
 AssetGroupAsset 
 = 
 ( 
 logo_mutate_operation 
 . 
 asset_group_asset_operation 
 . 
 create 
 ) 
 logo_asset_group_asset 
 . 
 field_type 
 = 
 client 
 . 
 enums 
 . 
 AssetFieldTypeEnum 
 . 
 LOGO 
 logo_asset_group_asset 
 . 
 asset_group 
 = 
 ( 
 asset_group_service 
 . 
 asset_group_path 
 ( 
 customer_id 
 , 
 _ASSET_GROUP_TEMPORARY_ID 
 , 
 ) 
 ) 
 logo_asset_group_asset 
 . 
 asset 
 = 
 asset_service 
 . 
 asset_path 
 ( 
 customer_id 
 , 
 image_asset_temp_id 
 ) 
 operations 
 . 
 append 
 ( 
 logo_mutate_operation 
 ) 
 return 
 operations 
 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. 
 results 
 : 
 Iterable 
 [ 
 MutateOperation 
 ] 
 = 
 response 
 . 
 mutate_operation_responses 
 suffix 
 = 
 "_result" 
 for 
 result 
 in 
 results 
 : 
 for 
 field_descriptor 
 , 
 value 
 in 
 result 
 . 
 _pb 
 . 
 ListFields 
 (): 
 if 
 field_descriptor 
 . 
 name 
 . 
 endswith 
 ( 
 suffix 
 ): 
 name 
 = 
 field_descriptor 
 . 
 name 
 [: 
 - 
 len 
 ( 
 suffix 
 )] 
 else 
 : 
 name 
 = 
 field_descriptor 
 . 
 name 
 print 
 ( 
 f 
 "Created a(n) 
 { 
 convert_snake_case_to_upper_case 
 ( 
 name 
 ) 
 } 
 with " 
 f 
 " 
 { 
 str 
 ( 
 value 
 ) 
 . 
 strip 
 () 
 } 
 ." 
 ) 
 def 
  
 create_asset_group_signal_operations 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 audience_id 
 : 
 Optional 
 [ 
 str 
 ] 
 ) 
 - 
> List 
 [ 
 MutateOperation 
 ]: 
  
 """Creates a list of MutateOperations that may create asset group signals. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 customer_id: a client customer ID. 
 audience_id: an optional audience ID. 
 Returns: 
 MutateOperations that create new asset group signals. 
 """ 
 googleads_service 
 : 
 GoogleAdsServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "GoogleAdsService" 
 ) 
 asset_group_resource_name 
 : 
 str 
 = 
 googleads_service 
 . 
 asset_group_path 
 ( 
 customer_id 
 , 
 _ASSET_GROUP_TEMPORARY_ID 
 ) 
 operations 
 : 
 List 
 [ 
 MutateOperation 
 ] 
 = 
 [] 
 if 
 audience_id 
 : 
 # Create an audience asset group signal. 
 # To learn more about Audience Signals, see: 
 # https://developers.google.com/google-ads/api/performance-max/asset-group-signals#audiences 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 operation 
 : 
 AssetGroupSignal 
 = 
 ( 
 mutate_operation 
 . 
 asset_group_signal_operation 
 . 
 create 
 ) 
 operation 
 . 
 asset_group 
 = 
 asset_group_resource_name 
 operation 
 . 
 audience 
 . 
 audience 
 = 
 googleads_service 
 . 
 audience_path 
 ( 
 customer_id 
 , 
 audience_id 
 ) 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 # Create a search theme asset group signal. 
 # To learn more about Search Themes Signals, see: 
 # https://developers.google.com/google-ads/api/performance-max/asset-group-signals#search_themes 
 mutate_operation 
 : 
 MutateOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "MutateOperation" 
 ) 
 operation 
 : 
 AssetGroupSignal 
 = 
 ( 
 mutate_operation 
 . 
 asset_group_signal_operation 
 . 
 create 
 ) 
 operation 
 . 
 asset_group 
 = 
 asset_group_resource_name 
 operation 
 . 
 search_theme 
 . 
 text 
 = 
 "travel" 
 operations 
 . 
 append 
 ( 
 mutate_operation 
 ) 
 return 
 operations 
 if 
 __name__ 
 == 
 "__main__" 
 : 
 parser 
 : 
 argparse 
 . 
 ArgumentParser 
 = 
 argparse 
 . 
 ArgumentParser 
 ( 
 description 
 = 
 ( 
 "Creates a Performance Max 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 
 ( 
 "-a" 
 , 
 "--audience_id" 
 , 
 type 
 = 
 str 
 , 
 help 
 = 
 "The ID of an audience." 
 , 
 ) 
 parser 
 . 
 add_argument 
 ( 
 "-b" 
 , 
 "--brand_guidelines_enabled" 
 , 
 type 
 = 
 bool 
 , 
 default 
 = 
 False 
 , 
 help 
 = 
 ( 
 "A boolean value indicating if the created campaign is enabled " 
 "for brand guidelines." 
 ), 
 ) 
 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 
 . 
 audience_id 
 , 
 args 
 . 
 brand_guidelines_enabled 
 , 
 ) 
 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 Performance Max campaign. 
 # 
 # For more information about Performance Max campaigns, see 
 # https://developers.google.com/google-ads/api/docs/performance-max/overview 
 # 
 # Prerequisites: 
 # - You must have at least one conversion action in the account. For 
 # more about conversion actions, see 
 # https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions 
 # 
 # This example uses the default customer conversion goals. For an example 
 # of setting campaign-specific conversion goals, see 
 # shopping_ads/add_performance_max_retail_campaign.rb 
 require 
  
 'optparse' 
 require 
  
 'date' 
 require 
  
 'open-uri' 
 require 
  
 'google/ads/google_ads' 
 # We specify temporary IDs that are specific to a single mutate request. 
 # Temporary IDs are always negative and unique within one mutate request. 
 # 
 # See https://developers.google.com/google-ads/api/docs/mutating/best-practices 
 # for further details. 
 # 
 # These temporary IDs are fixed because they are used in multiple places. 
 BUDGET_TEMPORARY_ID 
  
 = 
  
 "-1" 
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 = 
  
 "-2" 
 ASSET_GROUP_TEMPORARY_ID 
  
 = 
  
 "-3" 
 # There are also entities that will be created in the same request but do not 
 # need to be fixed temporary IDs because they are referenced only once. 
 def 
  
 next_temp_id 
  
 @id 
  
 ||= 
  
 ASSET_GROUP_TEMPORARY_ID 
 . 
 to_i 
  
 @id 
  
 -= 
  
 1 
 end 
 def 
  
 add_performance_max_campaign 
 ( 
  
 customer_id 
 , 
  
 audience_id 
 , 
  
 brand_guidelines_enabled 
 ) 
  
 # GoogleAdsClient will read a config file from 
  
 # ENV['HOME']/google_ads_config.rb when called without parameters 
  
 client 
  
 = 
  
 Google 
 :: 
 Ads 
 :: 
 GoogleAds 
 :: 
 GoogleAdsClient 
 . 
 new 
  
 # Performance Max campaigns require that repeated assets such as headlines 
  
 # and descriptions be created before the campaign. 
  
 # For the list of required assets for a Performance Max campaign, see 
  
 # https://developers.google.com/google-ads/api/docs/performance-max/assets 
  
 # 
  
 # Create the headlines. 
  
 headline_asset_resource_names 
  
 = 
  
 create_multiple_text_assets 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 [ 
  
 "Travel" 
 , 
  
 "Travel Reviews" 
 , 
  
 "Book travel" 
 , 
  
 ] 
 ) 
  
 # Create the descriptions. 
  
 description_asset_resource_names 
  
 = 
  
 create_multiple_text_assets 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 [ 
  
 "Take to the air!" 
 , 
  
 "Fly to the sky!" 
 , 
  
 ] 
 ) 
  
 # 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 Performance Max 
  
 # 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 
  
 = 
  
 create_campaign_budget_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 ) 
  
 performance_max_campaign_operation 
  
 = 
  
 create_performance_max_campaign_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 brand_guidelines_enabled 
 , 
  
 ) 
  
 campaign_criterion_operations 
  
 = 
  
 create_campaign_criterion_operations 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 ) 
  
 asset_group_operations 
  
 = 
  
 create_asset_group_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 headline_asset_resource_names 
 , 
  
 description_asset_resource_names 
 , 
  
 brand_guidelines_enabled 
 , 
  
 ) 
  
 asset_group_signal_operations 
  
 = 
  
 create_asset_group_signal_operations 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 audience_id 
 , 
  
 ) 
  
 # Send the operations in a single Mutate request. 
  
 response 
  
 = 
  
 client 
 . 
 service 
 . 
 google_ads 
 . 
 mutate 
 ( 
  
 customer_id 
 : 
  
 customer_id 
 , 
  
 mutate_operations 
 : 
  
 [ 
  
 # It's important to create these entities in this order because 
  
 # they depend on each other. 
  
 campaign_budget_operation 
 , 
  
 performance_max_campaign_operation 
 , 
  
 # Expand the list of multiple operations into the list of 
  
 # other mutate operations 
  
 campaign_criterion_operations 
 , 
  
 asset_group_operations 
 , 
  
 asset_group_signal_operations 
 , 
  
 ]. 
 flatten 
 ) 
  
 print_response_details 
 ( 
 response 
 ) 
 end 
 # 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. 
 def 
  
 create_campaign_budget_operation 
 ( 
 client 
 , 
  
 customer_id 
 ) 
  
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_budget_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 campaign_budget 
  
 do 
  
 | 
 cb 
 | 
  
 cb 
 . 
 name 
  
 = 
  
 "Performance Max campaign budget 
 #{ 
 SecureRandom 
 . 
 uuid 
 } 
 " 
  
 # The budget period already defaults to DAILY. 
  
 cb 
 . 
 amount_micros 
  
 = 
  
 50_000_000 
  
 cb 
 . 
 delivery_method 
  
 = 
  
 :STANDARD 
  
 # A Performance Max campaign cannot use a shared campaign budget. 
  
 cb 
 . 
 explicitly_shared 
  
 = 
  
 false 
  
 # Set 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 
 end 
 # Creates a MutateOperation that creates a new Performance Max 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_performance_max_campaign_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 brand_guidelines_enabled 
 ) 
  
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 campaign 
  
 do 
  
 | 
 c 
 | 
  
 c 
 . 
 name 
  
 = 
  
 "Performance Max campaign 
 #{ 
 SecureRandom 
 . 
 uuid 
 } 
 " 
  
 # Set the campaign status as PAUSED. The campaign is the only entity in 
  
 # the mutate request that should have its status set. 
  
 c 
 . 
 status 
  
 = 
  
 :PAUSED 
  
 # All Performance Max campaigns have an advertising_channel_type of 
  
 # PERFORMANCE_MAX. The advertising_channel_sub_type should not be set. 
  
 c 
 . 
 advertising_channel_type 
  
 = 
  
 :PERFORMANCE_MAX 
  
 # Bidding strategy must be set directly on the campaign. 
  
 # Setting a portfolio bidding strategy by resource name is not supported. 
  
 # Max Conversion and Maximize Conversion Value are the only strategies 
  
 # supported for Performance Max campaigns. 
  
 # An optional ROAS (Return on Advertising Spend) can be set for 
  
 # maximize_conversion_value. The ROAS value must be specified as a ratio in 
  
 # the API. It is calculated by dividing "total value" by "total spend". 
  
 # For more information on Maximize Conversion Value, see the support 
  
 # article: http://support.google.com/google-ads/answer/7684216. 
  
 # A target_roas of 3.5 corresponds to a 350% return on ad spend. 
  
 c 
 . 
 bidding_strategy_type 
  
 = 
  
 :MAXIMIZE_CONVERSION_VALUE 
  
 c 
 . 
 maximize_conversion_value 
  
 = 
  
 client 
 . 
 resource 
 . 
 maximize_conversion_value 
  
 do 
  
 | 
 mcv 
 | 
  
 mcv 
 . 
 target_roas 
  
 = 
  
 3 
 . 
 5 
  
 end 
  
 # Set the Final URL expansion opt out. This flag is specific to 
  
 # Performance Max campaigns. If opted out (true), only the final URLs in 
  
 # the asset group or URLs specified in the advertiser's Google Merchant 
  
 # Center or business data feeds are targeted. 
  
 # If opted in (false), the entire domain will be targeted. For best 
  
 # results, set this value to false to opt in and allow URL expansions. You 
  
 # can optionally add exclusions to limit traffic to parts of your website. 
  
 c 
 . 
 url_expansion_opt_out 
  
 = 
  
 false 
  
 # Set if the campaign is enabled for brand guidelines. For more 
  
 # information on brand guidelines, see 
  
 # https://support.google.com/google-ads/answer/14934472. 
  
 c 
 . 
 brand_guidelines_enabled 
  
 = 
  
 brand_guidelines_enabled 
  
 # Assign the resource name with a temporary ID. 
  
 c 
 . 
 resource_name 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
 customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 # Set the budget using the given budget resource name. 
  
 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 
  
 # Optional fields 
  
 c 
 . 
 start_date 
  
 = 
  
 DateTime 
 . 
 parse 
 (( 
 Date 
 . 
 today 
  
 + 
  
 1 
 ) 
 . 
 to_s 
 ) 
 . 
 strftime 
 ( 
 '%Y%m%d' 
 ) 
  
 c 
 . 
 end_date 
  
 = 
  
 DateTime 
 . 
 parse 
 ( 
 Date 
 . 
 today 
 . 
 next_year 
 . 
 to_s 
 ) 
 . 
 strftime 
 ( 
 '%Y%m%d' 
 ) 
  
 end 
  
 end 
 end 
 # Creates a list of MutateOperations that create new campaign criteria. 
 def 
  
 create_campaign_criterion_operations 
 ( 
 client 
 , 
  
 customer_id 
 ) 
  
 operations 
  
 = 
  
 [] 
  
 # Set the LOCATION campaign criteria. 
  
 # Target all of New York City except Brooklyn. 
  
 # Location IDs are listed here: 
  
 # https://developers.google.com/google-ads/api/reference/data/geotargets 
  
 # and they can also be retrieved using the GeoTargetConstantService as shown 
  
 # here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting 
  
 # 
  
 # We will add one positive location target for New York City (ID=1023191) 
  
 # and one negative location target for Brooklyn (ID=1022762). 
  
 # First, add the positive (negative = false) for New York City. 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_criterion_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 campaign_criterion 
  
 do 
  
 | 
 cc 
 | 
  
 cc 
 . 
 campaign 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
  
 customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 cc 
 . 
 location 
  
 = 
  
 client 
 . 
 resource 
 . 
 location_info 
  
 do 
  
 | 
 li 
 | 
  
 li 
 . 
 geo_target_constant 
  
 = 
  
 client 
 . 
 path 
 . 
 geo_target_constant 
 ( 
 "1023191" 
 ) 
  
 end 
  
 cc 
 . 
 negative 
  
 = 
  
 false 
  
 end 
  
 end 
  
 # Next add the negative target for Brooklyn. 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_criterion_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 campaign_criterion 
  
 do 
  
 | 
 cc 
 | 
  
 cc 
 . 
 campaign 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
  
 customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 cc 
 . 
 location 
  
 = 
  
 client 
 . 
 resource 
 . 
 location_info 
  
 do 
  
 | 
 li 
 | 
  
 li 
 . 
 geo_target_constant 
  
 = 
  
 client 
 . 
 path 
 . 
 geo_target_constant 
 ( 
 "1022762" 
 ) 
  
 end 
  
 cc 
 . 
 negative 
  
 = 
  
 true 
  
 end 
  
 end 
  
 # Set the LANGUAGE campaign criterion. 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_criterion_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 campaign_criterion 
  
 do 
  
 | 
 cc 
 | 
  
 cc 
 . 
 campaign 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
  
 customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 # Set the language. 
  
 # For a list of all language codes, see: 
  
 # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 
  
 cc 
 . 
 language 
  
 = 
  
 client 
 . 
 resource 
 . 
 language_info 
  
 do 
  
 | 
 li 
 | 
  
 li 
 . 
 language_constant 
  
 = 
  
 client 
 . 
 path 
 . 
 language_constant 
 ( 
 "1000" 
 ) 
  
 # English 
  
 end 
  
 end 
  
 end 
  
 operations 
 end 
 # Creates multiple text assets and returns the list of resource names. 
 def 
  
 create_multiple_text_assets 
 ( 
 client 
 , 
  
 customer_id 
 , 
  
 texts 
 ) 
  
 operations 
  
 = 
  
 texts 
 . 
 map 
  
 do 
  
 | 
 text 
 | 
  
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 asset 
  
 do 
  
 | 
 asset 
 | 
  
 asset 
 . 
 text_asset 
  
 = 
  
 client 
 . 
 resource 
 . 
 text_asset 
  
 do 
  
 | 
 text_asset 
 | 
  
 text_asset 
 . 
 text 
  
 = 
  
 text 
  
 end 
  
 end 
  
 end 
  
 end 
  
 # Send the operations in a single Mutate request. 
  
 response 
  
 = 
  
 client 
 . 
 service 
 . 
 google_ads 
 . 
 mutate 
 ( 
  
 customer_id 
 : 
  
 customer_id 
 , 
  
 mutate_operations 
 : 
  
 operations 
 , 
  
 ) 
  
 asset_resource_names 
  
 = 
  
 [] 
  
 response 
 . 
 mutate_operation_responses 
 . 
 each 
  
 do 
  
 | 
 result 
 | 
  
 if 
  
 result 
 . 
 asset_result 
  
 asset_resource_names 
 . 
 append 
 ( 
 result 
 . 
 asset_result 
 . 
 resource_name 
 ) 
  
 end 
  
 end 
  
 print_response_details 
 ( 
 response 
 ) 
  
 asset_resource_names 
 end 
 # Creates a list of MutateOperations that create a new asset_group. 
 # 
 # A temporary ID will be assigned to this asset group so that it can 
 # be referenced by other objects being created in the same Mutate request. 
 def 
  
 create_asset_group_operation 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 headline_asset_resource_names 
 , 
  
 description_asset_resource_names 
 , 
  
 brand_guidelines_enabled 
 ) 
  
 operations 
  
 = 
  
 [] 
  
 # Create the AssetGroup 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_group_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 asset_group 
  
 do 
  
 | 
 ag 
 | 
  
 ag 
 . 
 name 
  
 = 
  
 "Performance Max asset group 
 #{ 
 SecureRandom 
 . 
 uuid 
 } 
 " 
  
 ag 
 . 
 campaign 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
  
 customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 ) 
  
 ag 
 . 
 final_urls 
 << 
 "http://www.example.com" 
  
 ag 
 . 
 final_mobile_urls 
 << 
 "http://www.example.com" 
  
 ag 
 . 
 status 
  
 = 
  
 :PAUSED 
  
 ag 
 . 
 resource_name 
  
 = 
  
 client 
 . 
 path 
 . 
 asset_group 
 ( 
  
 customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 ) 
  
 end 
  
 end 
  
 # For the list of required assets for a Performance Max campaign, see 
  
 # https://developers.google.com/google-ads/api/docs/performance-max/assets 
  
 # 
  
 # An AssetGroup is linked to an Asset by creating a new AssetGroupAsset 
  
 # and providing: 
  
 #   the resource name of the AssetGroup 
  
 #   the resource name of the Asset 
  
 #   the field_type of the Asset in this AssetGroup. 
  
 # 
  
 # To learn more about AssetGroups, see 
  
 # https://developers.google.com/google-ads/api/docs/performance-max/asset-groups 
  
 # Link the previously created multiple text assets. 
  
 # Link the headline assets. 
  
 headline_asset_resource_names 
 . 
 each 
  
 do 
  
 | 
 resource_name 
 | 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_group_asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
  
 . 
 asset_group_asset 
  
 do 
  
 | 
 aga 
 | 
  
 aga 
 . 
 field_type 
  
 = 
  
 :HEADLINE 
  
 aga 
 . 
 asset_group 
  
 = 
  
 client 
 . 
 path 
 . 
 asset_group 
 ( 
  
 customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 ) 
  
 aga 
 . 
 asset 
  
 = 
  
 resource_name 
  
 end 
  
 end 
  
 end 
  
 #  Link the description assets. 
  
 description_asset_resource_names 
 . 
 each 
  
 do 
  
 | 
 resource_name 
 | 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_group_asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
  
 . 
 asset_group_asset 
  
 do 
  
 | 
 aga 
 | 
  
 aga 
 . 
 field_type 
  
 = 
  
 :DESCRIPTION 
  
 aga 
 . 
 asset_group 
  
 = 
  
 client 
 . 
 path 
 . 
 asset_group 
 ( 
  
 customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 ) 
  
 aga 
 . 
 asset 
  
 = 
  
 resource_name 
  
 end 
  
 end 
  
 end 
  
 # Create and link the long headline text asset. 
  
 operations 
  
 += 
  
 create_and_link_text_asset 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 "Travel the World" 
 , 
  
 :LONG_HEADLINE 
 ) 
  
 # Create and link the business name and logo asset. 
  
 operations 
  
 += 
  
 create_and_link_brand_assets 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 brand_guidelines_enabled 
 , 
  
 "Interplanetary Cruises" 
 , 
  
 "https://gaagl.page.link/bjYi" 
 , 
  
 "Marketing Logo" 
 ) 
  
 # Create and link the image assets. 
  
 # Create and link the Marketing Image Asset. 
  
 operations 
  
 += 
  
 create_and_link_image_asset 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 "https://gaagl.page.link/Eit5" 
 , 
  
 :MARKETING_IMAGE 
 , 
  
 "Marketing Image" 
 ) 
  
 # Create and link the Square Marketing Image Asset. 
  
 operations 
  
 += 
  
 create_and_link_image_asset 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 "https://gaagl.page.link/bjYi" 
 , 
  
 :SQUARE_MARKETING_IMAGE 
 , 
  
 "Square Marketing Image" 
 ) 
  
 operations 
 end 
 # Creates a list of MutateOperations that create a new linked text asset. 
 def 
  
 create_and_link_text_asset 
 ( 
 client 
 , 
  
 customer_id 
 , 
  
 text 
 , 
  
 field_type 
 ) 
  
 operations 
  
 = 
  
 [] 
  
 temp_id 
  
 = 
  
 next_temp_id 
  
 # Create the Text Asset. 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 asset 
  
 do 
  
 | 
 a 
 | 
  
 a 
 . 
 resource_name 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 temp_id 
 ) 
  
 a 
 . 
 text_asset 
  
 = 
  
 client 
 . 
 resource 
 . 
 text_asset 
  
 do 
  
 | 
 text_asset 
 | 
  
 text_asset 
 . 
 text 
  
 = 
  
 text 
  
 end 
  
 end 
  
 end 
  
 # Create an AssetGroupAsset to link the Asset to the AssetGroup. 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_group_asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
  
 . 
 asset_group_asset 
  
 do 
  
 | 
 aga 
 | 
  
 aga 
 . 
 field_type 
  
 = 
  
 field_type 
  
 aga 
 . 
 asset_group 
  
 = 
  
 client 
 . 
 path 
 . 
 asset_group 
 ( 
  
 customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 ) 
  
 aga 
 . 
 asset 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 temp_id 
 ) 
  
 end 
  
 end 
  
 operations 
 end 
 # Creates a list of MutateOperations that create a new linked image asset. 
 def 
  
 create_and_link_image_asset 
 ( 
 client 
 , 
  
 customer_id 
 , 
  
 url 
 , 
  
 field_type 
 , 
  
 asset_name 
 ) 
  
 operations 
  
 = 
  
 [] 
  
 temp_id 
  
 = 
  
 next_temp_id 
  
 # Create the Image Asset. 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 asset 
  
 do 
  
 | 
 a 
 | 
  
 a 
 . 
 resource_name 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 temp_id 
 ) 
  
 # Provide a unique friendly name to identify your asset. 
  
 # When there is an existing image asset with the same content but a different 
  
 # name, the new name will be dropped silently. 
  
 a 
 . 
 name 
  
 = 
  
 asset_name 
  
 a 
 . 
 type 
  
 = 
  
 :IMAGE 
  
 a 
 . 
 image_asset 
  
 = 
  
 client 
 . 
 resource 
 . 
 image_asset 
  
 do 
  
 | 
 image_asset 
 | 
  
 image_asset 
 . 
 data 
  
 = 
  
 get_image_bytes 
 ( 
 url 
 ) 
  
 end 
  
 end 
  
 end 
  
 # Create an AssetGroupAsset to link the Asset to the AssetGroup. 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_group_asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
  
 asset_group_asset 
  
 do 
  
 | 
 aga 
 | 
  
 aga 
 . 
 field_type 
  
 = 
  
 field_type 
  
 aga 
 . 
 asset_group 
  
 = 
  
 client 
 . 
 path 
 . 
 asset_group 
 ( 
  
 customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 , 
  
 ) 
  
 aga 
 . 
 asset 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 temp_id 
 ) 
  
 end 
  
 end 
  
 operations 
 end 
 # Creates a list of MutateOperations that create linked brand assets. 
 def 
  
 create_and_link_brand_assets 
 ( 
  
 client 
 , 
  
 customer_id 
 , 
  
 brand_guidelines_enabled 
 , 
  
 business_name 
 , 
  
 logo_url 
 , 
  
 logo_name 
 ) 
  
 operations 
  
 = 
  
 [] 
  
 # Create the Text Asset. 
  
 text_asset_temp_id 
  
 = 
  
 next_temp_id 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 asset 
  
 do 
  
 | 
 a 
 | 
  
 a 
 . 
 resource_name 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 text_asset_temp_id 
 ) 
  
 a 
 . 
 text_asset 
  
 = 
  
 client 
 . 
 resource 
 . 
 text_asset 
  
 do 
  
 | 
 text_asset 
 | 
  
 text_asset 
 . 
 text 
  
 = 
  
 business_name 
  
 end 
  
 end 
  
 end 
  
 # Create the Image Asset. 
  
 image_asset_temp_id 
  
 = 
  
 next_temp_id 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 asset 
  
 do 
  
 | 
 a 
 | 
  
 a 
 . 
 resource_name 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 image_asset_temp_id 
 ) 
  
 # Provide a unique friendly name to identify your asset. 
  
 # When there is an existing image asset with the same content but a different 
  
 # name, the new name will be dropped silently. 
  
 a 
 . 
 name 
  
 = 
  
 logo_name 
  
 a 
 . 
 type 
  
 = 
  
 :IMAGE 
  
 a 
 . 
 image_asset 
  
 = 
  
 client 
 . 
 resource 
 . 
 image_asset 
  
 do 
  
 | 
 image_asset 
 | 
  
 image_asset 
 . 
 data 
  
 = 
  
 get_image_bytes 
 ( 
 logo_url 
 ) 
  
 end 
  
 end 
  
 end 
  
 if 
  
 brand_guidelines_enabled 
  
 # Create CampaignAsset resources to link the Asset resources to the Campaign. 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
  
 campaign_asset 
  
 do 
  
 | 
 ca 
 | 
  
 ca 
 . 
 field_type 
  
 = 
  
 :BUSINESS_NAME 
  
 ca 
 . 
 campaign 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
  
 customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 , 
  
 ) 
  
 ca 
 . 
 asset 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 text_asset_temp_id 
 ) 
  
 end 
  
 end 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 campaign_asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
  
 campaign_asset 
  
 do 
  
 | 
 ca 
 | 
  
 ca 
 . 
 field_type 
  
 = 
  
 :LOGO 
  
 ca 
 . 
 campaign 
  
 = 
  
 client 
 . 
 path 
 . 
 campaign 
 ( 
  
 customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
 , 
  
 ) 
  
 ca 
 . 
 asset 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 image_asset_temp_id 
 ) 
  
 end 
  
 end 
  
 else 
  
 # Create AssetGroupAsset resources to link the Asset resources to the AssetGroup. 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_group_asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
  
 asset_group_asset 
  
 do 
  
 | 
 aga 
 | 
  
 aga 
 . 
 field_type 
  
 = 
  
 :BUSINESS_NAME 
  
 aga 
 . 
 asset_group 
  
 = 
  
 client 
 . 
 path 
 . 
 asset_group 
 ( 
  
 customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 , 
  
 ) 
  
 aga 
 . 
 asset 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 text_asset_temp_id 
 ) 
  
 end 
  
 end 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_group_asset_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
  
 asset_group_asset 
  
 do 
  
 | 
 aga 
 | 
  
 aga 
 . 
 field_type 
  
 = 
  
 :LOGO 
  
 aga 
 . 
 asset_group 
  
 = 
  
 client 
 . 
 path 
 . 
 asset_group 
 ( 
  
 customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 , 
  
 ) 
  
 aga 
 . 
 asset 
  
 = 
  
 client 
 . 
 path 
 . 
 asset 
 ( 
 customer_id 
 , 
  
 image_asset_temp_id 
 ) 
  
 end 
  
 end 
  
 end 
  
 operations 
 end 
 # Create a list of MutateOperations that create AssetGroupSignals. 
 def 
  
 create_asset_group_signal_operations 
 ( 
 client 
 , 
  
 customer_id 
 , 
  
 audience_id 
 ) 
  
 operations 
  
 = 
  
 [] 
  
 return 
  
 operations 
  
 if 
  
 audience_id 
 . 
 nil? 
  
 operations 
 << 
 client 
 . 
 operation 
 . 
 mutate 
  
 do 
  
 | 
 m 
 | 
  
 m 
 . 
 asset_group_signal_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
  
 asset_group_signal 
  
 do 
  
 | 
 ags 
 | 
  
 ags 
 . 
 asset_group 
  
 = 
  
 client 
 . 
 path 
 . 
 asset_group 
 ( 
  
 customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
 , 
  
 ) 
  
 ags 
 . 
 audience 
  
 = 
  
 client 
 . 
 resource 
 . 
 audience_info 
  
 do 
  
 | 
 ai 
 | 
  
 ai 
 . 
 audience 
  
 = 
  
 client 
 . 
 path 
 . 
 audience 
 ( 
 customer_id 
 , 
  
 audience_id 
 ) 
  
 end 
  
 end 
  
 end 
  
 operations 
 end 
 # Loads image data from a URL. 
 def 
  
 get_image_bytes 
 ( 
 url 
 ) 
  
 URI 
 . 
 open 
 ( 
 url 
 ) 
 . 
 read 
 end 
 # Prints the details of a MutateGoogleAdsResponse. 
 def 
  
 print_response_details 
 ( 
 response 
 ) 
  
 # Parse the mutate response to print details about the entities that 
  
 # were created by the request. 
  
 suffix 
  
 = 
  
 "_result" 
  
 response 
 . 
 mutate_operation_responses 
 . 
 each 
  
 do 
  
 | 
 result 
 | 
  
 result 
 . 
 to_h 
 . 
 select 
  
 { 
 | 
 k 
 , 
  
 v 
 | 
  
 v 
  
 } 
 . 
 each 
  
 do 
  
 | 
 name 
 , 
  
 value 
 | 
  
 if 
  
 name 
 . 
 to_s 
 . 
 end_with? 
 ( 
 suffix 
 ) 
  
 name 
  
 = 
  
 name 
 . 
 to_s 
 . 
 delete_suffix 
 ( 
 suffix 
 ) 
  
 end 
  
 puts 
  
 "Created a(n) 
 #{ 
 :: 
 Google 
 :: 
 Ads 
 :: 
 GoogleAds 
 :: 
 Utils 
 . 
 camelize 
 ( 
 name 
 ) 
 } 
 " 
  
 \ 
  
 "with 
 #{ 
 value 
 . 
 to_s 
 . 
 strip 
 } 
 ." 
  
 end 
  
 end 
 end 
 if 
  
 __FILE__ 
  
 == 
  
 $0 
  
 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' 
  
 options 
 [ 
 :audience_id 
 ] 
  
 = 
  
 nil 
  
 options 
 [ 
 :brand_guidelines_enabled 
 ] 
  
 = 
  
 false 
  
 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 
 ( 
 '-D' 
 , 
  
 '--audience-id AUDIENCE-ID' 
 , 
  
 String 
 , 
  
 'Audience ID (optional)' 
 ) 
  
 do 
  
 | 
 v 
 | 
  
 options 
 [ 
 :audience_id 
 ] 
  
 = 
  
 v 
  
 end 
  
 opts 
 . 
 on 
 ( 
 '-B' 
 , 
  
 '--brand-guidelines-enabled' 
 , 
  
 'Enable brand guidelines (optional)' 
 ) 
  
 do 
  
 options 
 [ 
 :brand_guidelines_enabled 
 ] 
  
 = 
  
 true 
  
 end 
  
 opts 
 . 
 separator 
  
 '' 
  
 opts 
 . 
 separator 
  
 'Help:' 
  
 opts 
 . 
 on_tail 
 ( 
 '-h' 
 , 
  
 '--help' 
 , 
  
 'Show this message' 
 ) 
  
 do 
  
 puts 
  
 opts 
  
 exit 
  
 end 
  
 end 
 . 
 parse! 
  
 begin 
  
 add_performance_max_campaign 
 ( 
  
 options 
 . 
 fetch 
 ( 
 :customer_id 
 ) 
 . 
 tr 
 ( 
 "-" 
 , 
  
 "" 
 ), 
  
 options 
 [ 
 :audience_id 
 ] 
 , 
  
 options 
 [ 
 :brand_guidelines_enabled 
 ] 
  
 ) 
  
 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 Performance Max campaign. 
 # 
 # For more information about Performance Max campaigns, see 
 # https://developers.google.com/google-ads/api/docs/performance-max/overview. 
 # 
 # Prerequisites: 
 # - You must have at least one conversion action in the account. For 
 #   more about conversion actions, see 
 #   https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions. 
 # 
 # This example uses the default customer conversion goals. For an example of 
 # setting campaign-specific conversion goals, see 
 # shopping_ads/add_performance_max_retail_campaign.pl. 
 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::MediaUtils 
 ; 
 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::CampaignAsset 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::Asset 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::AssetGroup 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::AssetGroupAsset 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Resources::AssetGroupSignal 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::MaximizeConversionValue 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::LocationInfo 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::LanguageInfo 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::TextAsset 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::ImageAsset 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Common::AudienceInfo 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::BudgetDeliveryMethodEnum 
  
 qw(STANDARD) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::CampaignStatusEnum 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::AdvertisingChannelTypeEnum 
  
 qw(PERFORMANCE_MAX) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::AssetGroupStatusEnum 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::AssetFieldTypeEnum 
  
 qw(HEADLINE DESCRIPTION LONG_HEADLINE BUSINESS_NAME LOGO MARKETING_IMAGE SQUARE_MARKETING_IMAGE) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Enums::EuPoliticalAdvertisingStatusEnum 
  
 qw(DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING) 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService::MutateOperation 
 ; 
 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::AssetService::AssetOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::AssetGroupService::AssetGroupOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::AssetGroupAssetService::AssetGroupAssetOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::AssetGroupSignalService::AssetGroupSignalOperation 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::CampaignAssetService::CampaignAssetOperation 
 ; 
 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) 
 ; 
 use 
  
 POSIX 
  
 qw(strftime) 
 ; 
 # We specify temporary IDs that are specific to a single mutate request. 
 # Temporary IDs are always negative and unique within one mutate request. 
 # 
 # See https://developers.google.com/google-ads/api/docs/mutating/best-practices 
 # for further details. 
 # 
 # These temporary IDs are fixed because they are used in multiple places. 
 use 
  
 constant 
  
 BUDGET_TEMPORARY_ID 
  
 = 
>  
 - 
 1 
 ; 
 use 
  
 constant 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 = 
>  
 - 
 2 
 ; 
 use 
  
 constant 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 = 
>  
 - 
 3 
 ; 
 # There are also entities that will be created in the same request but do not 
 # need to be fixed temporary IDs because they are referenced only once. 
 our 
  
 $next_temp_id 
  
 = 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 - 
  
 1 
 ; 
 sub 
  
 add_performance_max_campaign 
  
 { 
  
 my 
  
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $audience_id 
 , 
  
 $brand_guidelines_enabled 
 ) 
  
 = 
  
 @_ 
 ; 
  
 # Performance Max campaigns require that repeated assets such as headlines 
  
 # and descriptions be created before the campaign. 
  
 # For the list of required assets for a Performance Max campaign, see 
  
 # https://developers.google.com/google-ads/api/docs/performance-max/assets. 
  
 # 
  
 # Create the headlines. 
  
 my 
  
 $headline_asset_resource_names 
  
 = 
  
 create_multiple_text_assets 
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 [ 
 "Travel" 
 , 
  
 "Travel Reviews" 
 , 
  
 "Book travel" 
 ]); 
  
 # Create the descriptions. 
  
 my 
  
 $description_asset_resource_names 
  
 = 
  
 create_multiple_text_assets 
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 [ 
 "Take to the air!" 
 , 
  
 "Fly to the sky!" 
 ]); 
  
 # It's important to create the below entities in this order because they depend 
  
 # on each other. 
  
 my 
  
 $operations 
  
 = 
  
 [] 
 ; 
  
 # 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 Performance Max 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. 
  
 push 
  
 @$operations 
 , 
  
 create_campaign_budget_operation 
 ( 
 $customer_id 
 ); 
  
 push 
  
 @$operations 
 , 
  
 create_performance_max_campaign_operation 
 ( 
 $customer_id 
 , 
  
 $brand_guidelines_enabled 
 ); 
  
 push 
  
 @$operations 
 , 
  
 @ 
 { 
 create_campaign_criterion_operations 
 ( 
 $customer_id 
 )}; 
  
 push 
  
 @$operations 
 , 
  
 @ 
 { 
  
 create_asset_group_operations 
 ( 
  
 $customer_id 
 , 
  
 $headline_asset_resource_names 
 , 
  
 $description_asset_resource_names 
 , 
  
 $brand_guidelines_enabled 
  
 )}; 
  
 push 
  
 @$operations 
 , 
  
 @ 
 { 
 create_asset_group_signal_operations 
 ( 
 $customer_id 
 , 
  
 $audience_id 
 )}; 
  
 # Issue a mutate request to create everything and print its information. 
  
 my 
  
 $mutate_google_ads_response 
  
 = 
  
 $api_client 
 - 
> GoogleAdsService 
 () 
 - 
> mutate 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id 
 , 
  
 mutateOperations 
  
 = 
>  
 $operations 
  
 }); 
  
 print_response_details 
 ( 
 $mutate_google_ads_response 
 ); 
  
 return 
  
 1 
 ; 
 } 
 # 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 
 ) 
  
 = 
  
 @_ 
 ; 
  
 # Create a mutate operation that creates a campaign budget operation. 
  
 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 
 ( 
  
 { 
  
 # 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 
  
 ), 
  
 name 
  
 = 
>  
 "Performance Max campaign budget #" 
  
 . 
  
 uniqid 
 (), 
  
 # The budget period already defaults to DAILY. 
  
 amountMicros 
  
 = 
>  
 50000000 
 , 
  
 deliveryMethod 
  
 = 
>  
 STANDARD 
 , 
  
 # A Performance Max campaign cannot use a shared campaign budget. 
  
 explicitlyShared 
  
 = 
>  
 "false" 
 , 
  
 })})}); 
 } 
 # Creates a MutateOperation that creates a new Performance Max 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_performance_max_campaign_operation 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 , 
  
 $brand_guidelines_enabled 
 ) 
  
 = 
  
 @_ 
 ; 
  
 # Create a mutate operation that creates a campaign operation. 
  
 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 
 ({ 
  
 # Assign the resource name with a temporary ID. 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 name 
  
 = 
>  
 "Performance Max campaign #" 
  
 . 
  
 uniqid 
 (), 
  
 # Set the budget using the given budget resource name. 
  
 campaignBudget 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign_budget 
 ( 
  
 $customer_id 
 , 
  
 BUDGET_TEMPORARY_ID 
  
 ), 
  
 # Set the campaign status as PAUSED. The campaign is the only entity in 
  
 # the mutate request that should have its status set. 
  
 status 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Enums::CampaignStatusEnum:: 
 PAUSED 
 , 
  
 # All Performance Max campaigns have an advertisingChannelType of 
  
 # PERFORMANCE_MAX. The advertisingChannelSubType should not be set. 
  
 advertisingChannelType 
  
 = 
>  
 PERFORMANCE_MAX 
 , 
  
 # Bidding strategy must be set directly on the campaign. 
  
 # Setting a portfolio bidding strategy by resource name is not supported. 
  
 # Max Conversion and Maximize Conversion Value are the only strategies 
  
 # supported for Performance Max campaigns. 
  
 # An optional ROAS (Return on Advertising Spend) can be set for 
  
 # maximizeConversionValue. The ROAS value must be specified as a ratio in 
  
 # the API. It is calculated by dividing "total value" by "total spend". 
  
 # For more information on Maximize Conversion Value, see the support 
  
 # article: http://support.google.com/google-ads/answer/7684216. 
  
 # A targetRoas of 3.5 corresponds to a 350% return on ad spend. 
  
 maximizeConversionValue 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 MaximizeConversionValue 
 - 
>  
 new 
 ({ 
  
 targetRoas 
  
 = 
>  
 3.5 
  
 } 
  
 ), 
  
 # Set the final URL expansion opt out. This flag is specific to 
  
 # Performance Max campaigns. If opted out (true), only the final URLs in 
  
 # the asset group or URLs specified in the advertiser's Google Merchant 
  
 # Center or business data feeds are targeted. 
  
 # If opted in (false), the entire domain will be targeted. For best 
  
 # results, set this value to false to opt in and allow URL expansions. You 
  
 # can optionally add exclusions to limit traffic to parts of your website. 
  
 urlExpansionOptOut 
  
 = 
>  
 "false" 
 , 
  
 # Set if the campaign is enabled for brand guidelines. For more information 
  
 # on brand guidelines, see https://support.google.com/google-ads/answer/14934472. 
  
 brandGuidelinesEnabled 
  
 = 
>  
 $brand_guidelines_enabled 
 , 
  
 # Optional fields. 
  
 startDate 
  
 = 
>  
 strftime 
 ( 
 "%Y%m%d" 
 , 
  
 localtime 
 ( 
 time 
  
 + 
  
 60 
  
 * 
  
 60 
  
 * 
  
 24 
 )), 
  
 endDate 
  
 = 
>  
 strftime 
 ( 
 "%Y%m%d" 
 , 
  
 localtime 
 ( 
 time 
  
 + 
  
 60 
  
 * 
  
 60 
  
 * 
  
 24 
  
 * 
  
 365 
 )), 
  
 # 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 
  
 })})}); 
 } 
 # Creates a list of MutateOperations that create new campaign criteria. 
 sub 
  
 create_campaign_criterion_operations 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $operations 
  
 = 
  
 [] 
 ; 
  
 # Set the LOCATION campaign criteria. 
  
 # Target all of New York City except Brooklyn. 
  
 # Location IDs are listed here: 
  
 # https://developers.google.com/google-ads/api/reference/data/geotargets 
  
 # and they can also be retrieved using the GeoTargetConstantService as shown 
  
 # here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting. 
  
 # 
  
 # We will add one positive location target for New York City (ID=1023191) 
  
 # and one negative location target for Brooklyn (ID=1022762). 
  
 # First, add the positive (negative = false) for New York City. 
  
 push 
  
 @$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 
 ({ 
  
 campaign 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 location 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 LocationInfo 
 - 
> new 
 ({ 
  
 geoTargetConstant 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 geo_target_constant 
 ( 
  
 1023191 
 )} 
  
 ), 
  
 negative 
  
 = 
>  
 "false" 
  
 })})}); 
  
 # Next add the negative target for Brooklyn. 
  
 push 
  
 @$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 
 ({ 
  
 campaign 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 location 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 LocationInfo 
 - 
> new 
 ({ 
  
 geoTargetConstant 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 geo_target_constant 
 ( 
  
 1022762 
 )} 
  
 ), 
  
 negative 
  
 = 
>  
 "true" 
  
 })})}); 
  
 # Set the LANGUAGE campaign criterion. 
  
 push 
  
 @$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 
 ({ 
  
 campaign 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 # Set the language. 
  
 # For a list of all language codes, see: 
  
 # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7. 
  
 language 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 LanguageInfo 
 - 
> new 
 ({ 
  
 languageConstant 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 language_constant 
 ( 
  
 1000 
 ) 
  
 # English 
  
 })})})}); 
  
 return 
  
 $operations 
 ; 
 } 
 # Creates multiple text assets and returns the list of resource names. 
 sub 
  
 create_multiple_text_assets 
  
 { 
  
 my 
  
 ( 
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $texts 
 ) 
  
 = 
  
 @_ 
 ; 
  
 # Here again we use the GoogleAdService to create multiple text assets in a 
  
 # single request. 
  
 my 
  
 $operations 
  
 = 
  
 [] 
 ; 
  
 foreach 
  
 my 
  
 $text 
  
 ( 
 @$texts 
 ) 
  
 { 
  
 # Create a mutate operation for a text asset. 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
  
 - 
> new 
 ({ 
  
 assetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetService:: 
 AssetOperation 
 - 
>  
 new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 Asset 
 - 
> new 
 ({ 
  
 textAsset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 TextAsset 
 - 
> new 
 ({ 
  
 text 
  
 = 
>  
 $text 
  
 })})})}); 
  
 } 
  
 # Issue a mutate request to add all assets. 
  
 my 
  
 $mutate_google_ads_response 
  
 = 
  
 $api_client 
 - 
> GoogleAdsService 
 () 
 - 
> mutate 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id 
 , 
  
 mutateOperations 
  
 = 
>  
 $operations 
  
 }); 
  
 my 
  
 $asset_resource_names 
  
 = 
  
 [] 
 ; 
  
 foreach 
  
 my 
  
 $response 
  
 ( 
 @ 
 { 
 $mutate_google_ads_response 
 - 
> { 
 mutateOperationResponses 
 }}) 
  
 { 
  
 push 
  
 @$asset_resource_names 
 , 
  
 $response 
 - 
> { 
 assetResult 
 }{ 
 resourceName 
 }; 
  
 } 
  
 print_response_details 
 ( 
 $mutate_google_ads_response 
 ); 
  
 return 
  
 $asset_resource_names 
 ; 
 } 
 # Creates a list of MutateOperations that create a new asset group. 
 # 
 # A temporary ID will be assigned to this asset group so that it can be referenced 
 # by other objects being created in the same mutate request. 
 sub 
  
 create_asset_group_operations 
  
 { 
  
 my 
  
 ( 
  
 $customer_id 
 , 
  
 $headline_asset_resource_names 
 , 
  
 $description_asset_resource_names 
 , 
  
 $brand_guidelines_enabled 
  
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $operations 
  
 = 
  
 [] 
 ; 
  
 # Create a mutate operation that creates an asset group operation. 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 assetGroupOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetGroupService:: 
 AssetGroupOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AssetGroup 
 - 
> new 
 ({ 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset_group 
 ( 
  
 $customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 ), 
  
 name 
  
 = 
>  
 "Performance Max asset group #" 
  
 . 
  
 uniqid 
 (), 
  
 campaign 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 finalUrls 
  
 = 
>  
 [ 
 "http://www.example.com" 
 ], 
  
 finalMobileUrls 
  
 = 
>  
 [ 
 "http://www.example.com" 
 ], 
  
 status 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Enums::AssetGroupStatusEnum:: 
 PAUSED 
  
 })})}); 
  
 # For the list of required assets for a Performance Max campaign, see 
  
 # https://developers.google.com/google-ads/api/docs/performance-max/assets. 
  
 # An AssetGroup is linked to an Asset by creating a new AssetGroupAsset 
  
 # and providing: 
  
 # - the resource name of the AssetGroup 
  
 # - the resource name of the Asset 
  
 # - the fieldType of the Asset in this AssetGroup 
  
 # 
  
 # To learn more about AssetGroups, see 
  
 # https://developers.google.com/google-ads/api/docs/performance-max/asset-groups. 
  
 # Link the previously created multiple text assets. 
  
 # Link the headline assets. 
  
 foreach 
  
 my 
  
 $resource_name 
  
 ( 
 @$headline_asset_resource_names 
 ) 
  
 { 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
  
 - 
> new 
 ({ 
  
 assetGroupAssetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetGroupAssetService:: 
 AssetGroupAssetOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AssetGroupAsset 
 - 
> new 
 ({ 
  
 asset 
  
 = 
>  
 $resource_name 
 , 
  
 assetGroup 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset_group 
 ( 
  
 $customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 ), 
  
 fieldType 
  
 = 
>  
 HEADLINE 
  
 })})}); 
  
 } 
  
 # Link the description assets. 
  
 foreach 
  
 my 
  
 $resource_name 
  
 ( 
 @$description_asset_resource_names 
 ) 
  
 { 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
  
 - 
> new 
 ({ 
  
 assetGroupAssetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetGroupAssetService:: 
 AssetGroupAssetOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AssetGroupAsset 
 - 
> new 
 ({ 
  
 asset 
  
 = 
>  
 $resource_name 
 , 
  
 assetGroup 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset_group 
 ( 
  
 $customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 ), 
  
 fieldType 
  
 = 
>  
 DESCRIPTION 
  
 })})}); 
  
 } 
  
 # Create and link the long headline text asset. 
  
 push 
  
 @$operations 
 , 
  
 @ 
 { 
 create_and_link_text_asset 
 ( 
 $customer_id 
 , 
  
 "Travel the World" 
 , 
  
 LONG_HEADLINE 
 )}; 
  
 # Create and link the business name and logo asset. 
  
 push 
  
 @$operations 
 , 
  
 @ 
 { 
  
 create_and_link_brand_assets 
 ( 
  
 $customer_id 
 , 
  
 $brand_guidelines_enabled 
 , 
  
 "Interplanetary Cruises" 
 , 
  
 "https://gaagl.page.link/bjYi" 
 , 
  
 "Marketing Logo" 
  
 )}; 
  
 # Create and link the image assets. 
  
 # Create and link the marketing image asset. 
  
 push 
  
 @$operations 
 , 
  
 @ 
 { 
  
 create_and_link_image_asset 
 ( 
  
 $customer_id 
 , 
  
 "https://gaagl.page.link/Eit5" 
 , 
  
 MARKETING_IMAGE 
 , 
  
 "Marketing Image" 
  
 )}; 
  
 # Create and link the square marketing image asset. 
  
 push 
  
 @$operations 
 , 
  
 @ 
 { 
  
 create_and_link_image_asset 
 ( 
  
 $customer_id 
 , 
  
 "https://gaagl.page.link/bjYi" 
 , 
  
 SQUARE_MARKETING_IMAGE 
 , 
  
 "Square Marketing Image" 
  
 )}; 
  
 return 
  
 $operations 
 ; 
 } 
 # Creates a list of MutateOperations that create a new linked text asset. 
 sub 
  
 create_and_link_text_asset 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 , 
  
 $text 
 , 
  
 $field_type 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $operations 
  
 = 
  
 [] 
 ; 
  
 # Create a new mutate operation for a text asset. 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 assetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetService:: 
 AssetOperation 
 - 
>  
 new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 Asset 
 - 
> new 
 ({ 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $next_temp_id 
  
 ), 
  
 textAsset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 TextAsset 
 - 
> new 
 ({ 
  
 text 
  
 = 
>  
 $text 
  
 })})})}); 
  
 # Create an asset group asset to link the asset to the asset group. 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 assetGroupAssetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetGroupAssetService:: 
 AssetGroupAssetOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AssetGroupAsset 
 - 
> new 
 ({ 
  
 asset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $next_temp_id 
  
 ), 
  
 assetGroup 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset_group 
 ( 
  
 $customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 ), 
  
 fieldType 
  
 = 
>  
 $field_type 
  
 })})}); 
  
 $next_temp_id 
 -- 
 ; 
  
 return 
  
 $operations 
 ; 
 } 
 # Creates a list of MutateOperations that create a new linked image asset. 
 sub 
  
 create_and_link_image_asset 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 , 
  
 $url 
 , 
  
 $field_type 
 , 
  
 $asset_name 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $operations 
  
 = 
  
 [] 
 ; 
  
 # Create a new mutate operation for an image asset. 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 assetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetService:: 
 AssetOperation 
 - 
>  
 new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 Asset 
 - 
> new 
 ({ 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $next_temp_id 
  
 ), 
  
 # Provide a unique friendly name to identify your asset. 
  
 # When there is an existing image asset with the same content but a different 
  
 # name, the new name will be dropped silently. 
  
 name 
  
 = 
>  
 $asset_name 
 , 
  
 imageAsset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 ImageAsset 
 - 
> new 
 ({ 
  
 data 
  
 = 
>  
 get_base64_data_from_url 
 ( 
 $url 
 )})})})}); 
  
 # Create an asset group asset to link the asset to the asset group. 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 assetGroupAssetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetGroupAssetService:: 
 AssetGroupAssetOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AssetGroupAsset 
 - 
> new 
 ({ 
  
 asset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $next_temp_id 
  
 ), 
  
 assetGroup 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset_group 
 ( 
  
 $customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 ), 
  
 fieldType 
  
 = 
>  
 $field_type 
  
 })})}); 
  
 $next_temp_id 
 -- 
 ; 
  
 return 
  
 $operations 
 ; 
 } 
 # Creates a list of MutateOperations that create linked brand assets. 
 sub 
  
 create_and_link_brand_assets 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 , 
  
 $brand_guidelines_enabled 
 , 
  
 $business_name 
 , 
  
 $logo_url 
 , 
  
 $logo_name 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $operations 
  
 = 
  
 [] 
 ; 
  
 # Create the text asset. 
  
 my 
  
 $text_asset_temp_id 
  
 = 
  
 $next_temp_id 
 -- 
 ; 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 assetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetService:: 
 AssetOperation 
 - 
>  
 new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 Asset 
 - 
> new 
 ({ 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $text_asset_temp_id 
  
 ), 
  
 textAsset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 TextAsset 
 - 
> new 
 ({ 
  
 text 
  
 = 
>  
 $business_name 
  
 })})})}); 
  
 # Create the image asset. 
  
 my 
  
 $image_asset_temp_id 
  
 = 
  
 $next_temp_id 
 -- 
 ; 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 assetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetService:: 
 AssetOperation 
 - 
>  
 new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 Asset 
 - 
> new 
 ({ 
  
 resourceName 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $image_asset_temp_id 
  
 ), 
  
 # Provide a unique friendly name to identify your asset. 
  
 # When there is an existing image asset with the same content but a different 
  
 # name, the new name will be dropped silently. 
  
 name 
  
 = 
>  
 $logo_name 
 , 
  
 imageAsset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 ImageAsset 
 - 
> new 
 ({ 
  
 data 
  
 = 
>  
 get_base64_data_from_url 
 ( 
 $logo_url 
 )})})})}); 
  
 if 
  
 ( 
 $brand_guidelines_enabled 
 ) 
  
 { 
  
 # Create CampaignAsset resources to link the Asset resources to the Campaign. 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
  
 - 
> new 
 ({ 
  
 campaignAssetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::CampaignAssetService:: 
 CampaignAssetOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 CampaignAsset 
 - 
> new 
 ({ 
  
 fieldType 
  
 = 
>  
 BUSINESS_NAME 
 , 
  
 campaign 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 asset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $text_asset_temp_id 
  
 )})})}); 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
  
 - 
> new 
 ({ 
  
 campaignAssetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::CampaignAssetService:: 
 CampaignAssetOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 CampaignAsset 
 - 
> new 
 ({ 
  
 fieldType 
  
 = 
>  
 LOGO 
 , 
  
 campaign 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 campaign 
 ( 
  
 $customer_id 
 , 
  
 PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID 
  
 ), 
  
 asset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $image_asset_temp_id 
  
 )})})}); 
  
 } 
  
 else 
  
 { 
  
 # Create AssetGroupAsset resources to link the Asset resources to the AssetGroup. 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
  
 - 
> new 
 ({ 
  
 assetGroupAssetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetGroupAssetService:: 
 AssetGroupAssetOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AssetGroupAsset 
 - 
> new 
 ({ 
  
 asset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $text_asset_temp_id 
  
 ), 
  
 assetGroup 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset_group 
 ( 
  
 $customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 ), 
  
 fieldType 
  
 = 
>  
 BUSINESS_NAME 
  
 })})}); 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
  
 - 
> new 
 ({ 
  
 assetGroupAssetOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetGroupAssetService:: 
 AssetGroupAssetOperation 
  
 - 
> new 
 ({ 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AssetGroupAsset 
 - 
> new 
 ({ 
  
 asset 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset 
 ( 
  
 $customer_id 
 , 
  
 $image_asset_temp_id 
  
 ), 
  
 assetGroup 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset_group 
 ( 
  
 $customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 ), 
  
 fieldType 
  
 = 
>  
 LOGO 
  
 })})}); 
  
 } 
  
 return 
  
 $operations 
 ; 
 } 
 # Creates a list of MutateOperations that create asset group signals. 
 sub 
  
 create_asset_group_signal_operations 
  
 { 
  
 my 
  
 ( 
 $customer_id 
 , 
  
 $audience_id 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $operations 
  
 = 
  
 [] 
 ; 
  
 return 
  
 $operations 
  
 if 
  
 not 
  
 defined 
  
 $audience_id 
 ; 
  
 push 
  
 @$operations 
 , 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 MutateOperation 
 - 
>  
 new 
 ({ 
  
 assetGroupSignalOperation 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::AssetGroupSignalService:: 
 AssetGroupSignalOperation 
  
 - 
> new 
 ({ 
  
 # To learn more about Audience Signals, see: 
  
 # https://developers.google.com/google-ads/api/docs/performance-max/asset-groups#audience_signals 
  
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 AssetGroupSignal 
 - 
> new 
 ({ 
  
 assetGroup 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 asset_group 
 ( 
  
 $customer_id 
 , 
  
 ASSET_GROUP_TEMPORARY_ID 
  
 ), 
  
 audience 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Common:: 
 AudienceInfo 
 - 
> new 
 ({ 
  
 audience 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 audience 
 ( 
  
 $customer_id 
 , 
  
 $audience_id 
  
 )})})})}); 
  
 return 
  
 $operations 
 ; 
 } 
 # 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. 
 sub 
  
 print_response_details 
  
 { 
  
 my 
  
 ( 
 $mutate_google_ads_response 
 ) 
  
 = 
  
 @_ 
 ; 
  
 foreach 
  
 my 
  
 $response 
  
 ( 
 @ 
 { 
 $mutate_google_ads_response 
 - 
> { 
 mutateOperationResponses 
 }}) 
  
 { 
  
 my 
  
 $result_type 
  
 = 
  
 [ 
 keys 
  
 %$response 
 ] 
 - 
> [ 
 0 
 ]; 
  
 printf 
  
 "Created a(n) %s with '%s'.\n" 
 , 
  
 ucfirst 
  
 $result_type 
  
 =~ 
  
 s/Result$// 
 r 
 , 
  
 $response 
 - 
> { 
 $result_type 
 }{ 
 resourceName 
 }; 
  
 } 
 } 
 # 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 
 ); 
 my 
  
 $customer_id 
  
 = 
  
 undef 
 ; 
 my 
  
 $audience_id 
  
 = 
  
 undef 
 ; 
 my 
  
 $brand_guidelines_enabled 
  
 = 
  
 "false" 
 ; 
 # Parameters passed on the command line will override any parameters set in code. 
 GetOptions 
 ( 
  
 "customer_id=s" 
  
 = 
>  
 \ 
 $customer_id 
 , 
  
 "audience_id=i" 
  
 = 
>  
 \ 
 $audience_id 
 , 
  
 "brand_guidelines_enabled=s" 
  
 = 
>  
 \ 
 $brand_guidelines_enabled 
 ); 
 # 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_performance_max_campaign 
 ( 
  
 $api_client 
 , 
  
 $customer_id 
  
 =~ 
  
 s/-//g 
 r 
 , 
  
 $audience_id 
 , 
  
 $brand_guidelines_enabled 
 ); 
 =pod 
 =head1 NAME 
 add_performance_max_campaign 
 =head1 DESCRIPTION 
 This example shows how to create a Performance Max campaign. 
 For more information about Performance Max campaigns, see 
 https://developers.google.com/google-ads/api/docs/performance-max/overview. 
 Prerequisites: 
 - You must have at least one conversion action in the account. For 
 more about conversion actions, see 
 https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions. 
 This example uses the default customer conversion goals. For an example of 
 setting campaign-specific conversion goals, see 
 shopping_ads/add_performance_max_retail_campaign.pl. 
 =head1 SYNOPSIS 
 add_performance_max_campaign.pl [options] 
 -help                       Show the help message. 
 -customer_id                The Google Ads customer ID. 
 -audience_id                [optional] An audience ID to use to improve the 
 targeting of the Performance Max campaign. 
 -brand_guidelines_enabled	[optional] A boolean value indicating if the campaign is enabled for brand guidelines. Defaults to false. 
 =cut 
  
  
Create a Mobile Website
View Site in Mobile | Classic
Share by: