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