Java
// Copyright 2020 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.campaignmanagement; import static com.google.ads.googleads.examples.utils.CodeSampleHelper.getPrintableDateTime; 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.v17.common.ExpandedTextAdInfo; import com.google.ads.googleads.v17.common.KeywordInfo; import com.google.ads.googleads.v17.common.ManualCpc; import com.google.ads.googleads.v17.enums.AdGroupAdStatusEnum.AdGroupAdStatus; import com.google.ads.googleads.v17.enums.AdGroupCriterionStatusEnum.AdGroupCriterionStatus; import com.google.ads.googleads.v17.enums.AdGroupTypeEnum.AdGroupType; import com.google.ads.googleads.v17.enums.AdvertisingChannelTypeEnum.AdvertisingChannelType; import com.google.ads.googleads.v17.enums.BudgetDeliveryMethodEnum.BudgetDeliveryMethod; import com.google.ads.googleads.v17.enums.CampaignStatusEnum.CampaignStatus; import com.google.ads.googleads.v17.enums.KeywordMatchTypeEnum.KeywordMatchType; import com.google.ads.googleads.v17.errors.GoogleAdsError; import com.google.ads.googleads.v17.errors.GoogleAdsException; import com.google.ads.googleads.v17.resources.Ad; import com.google.ads.googleads.v17.resources.AdGroup; import com.google.ads.googleads.v17.resources.AdGroupAd; import com.google.ads.googleads.v17.resources.AdGroupCriterion; import com.google.ads.googleads.v17.resources.BatchJob; import com.google.ads.googleads.v17.resources.Campaign; import com.google.ads.googleads.v17.resources.CampaignBudget; import com.google.ads.googleads.v17.resources.CampaignCriterion; import com.google.ads.googleads.v17.services.AdGroupAdOperation; import com.google.ads.googleads.v17.services.AdGroupCriterionOperation; import com.google.ads.googleads.v17.services.AdGroupOperation; import com.google.ads.googleads.v17.services.AddBatchJobOperationsRequest; import com.google.ads.googleads.v17.services.AddBatchJobOperationsResponse; import com.google.ads.googleads.v17.services.BatchJobOperation; import com.google.ads.googleads.v17.services.BatchJobResult; import com.google.ads.googleads.v17.services.BatchJobServiceClient; import com.google.ads.googleads.v17.services.BatchJobServiceClient.ListBatchJobResultsPagedResponse; import com.google.ads.googleads.v17.services.CampaignBudgetOperation; import com.google.ads.googleads.v17.services.CampaignCriterionOperation; import com.google.ads.googleads.v17.services.CampaignOperation; import com.google.ads.googleads.v17.services.ListBatchJobResultsRequest; import com.google.ads.googleads.v17.services.MutateOperation; import com.google.ads.googleads.v17.services.MutateOperationResponse.ResponseCase; import com.google.ads.googleads.v17.utils.ResourceNames; import com.google.api.gax.longrunning.OperationFuture; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * This example adds complete campaigns including campaign budgets, campaigns, ad groups and * keywords using BatchJobService. */ public class AddCompleteCampaignsUsingBatchJob { private static final int NUMBER_OF_CAMPAIGNS_TO_ADD = 2; private static final int NUMBER_OF_AD_GROUPS_TO_ADD = 2; private static final int NUMBER_OF_KEYWORDS_TO_ADD = 4; private static final int MAX_TOTAL_POLL_INTERVAL_SECONDS = 60; private static final int PAGE_SIZE = 1000; /** The negative temporary ID used in mutate job operations. */ private static long temporaryId = -1; private static class AddCompleteCampaignsUsingBatchJobParams extends CodeSampleParams { @Parameter(names = ArgumentNames.CUSTOMER_ID, required = true) private Long customerId; } public static void main(String[] args) throws IOException { AddCompleteCampaignsUsingBatchJobParams params = new AddCompleteCampaignsUsingBatchJobParams(); 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"); } 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 AddCompleteCampaignsUsingBatchJob().runExample(googleAdsClient, params.customerId); } 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); } } } /** * Runs the example. * * @param googleAdsClient the Google Ads API client. * @param customerId the client customer ID. * @throws GoogleAdsException if an API request failed with one or more service errors. */ private void runExample(GoogleAdsClient googleAdsClient, long customerId) { try (BatchJobServiceClient batchJobServiceClient = googleAdsClient.getLatestVersion().createBatchJobServiceClient()) { String batchJobResourceName = createBatchJob(batchJobServiceClient, customerId); addAllBatchJobOperations(batchJobServiceClient, customerId, batchJobResourceName); OperationFuture operationResponse = runBatchJob(batchJobServiceClient, batchJobResourceName); pollBatchJob(operationResponse); fetchAndPrintResults(batchJobServiceClient, batchJobResourceName); } } /** * Creates a new mutate job for the specified customer ID. * * @param batchJobServiceClient the mutate job service client. * @param customerId the client customer ID. * @return the resource name of the created mutate job. */ private String createBatchJob(BatchJobServiceClient batchJobServiceClient, long customerId) { BatchJobOperation operation = BatchJobOperation.newBuilder().setCreate(BatchJob.newBuilder().build()).build(); String batchJobResourceName = batchJobServiceClient .mutateBatchJob(Long.toString(customerId), operation) .getResult() .getResourceName(); System.out.printf("Created a mutate job with resource name: '%s'.%n", batchJobResourceName); return batchJobResourceName; } /** * Adds all mutate job operations to the mutate job. As this is the first time for this mutate * job, the sequence token is not set. The response will contain the next sequence token that you * can use to upload more operations in the future. * * @param batchJobServiceClient the mutate job service client. * @param customerId the client customer ID. * @param batchJobResourceName the resource name of mutate job to which the mutate job operations * will be added. */ private void addAllBatchJobOperations( BatchJobServiceClient batchJobServiceClient, long customerId, String batchJobResourceName) { AddBatchJobOperationsResponse response = batchJobServiceClient.addBatchJobOperations( AddBatchJobOperationsRequest.newBuilder() .setResourceName(batchJobResourceName) .addAllMutateOperations(buildAllOperations(customerId)) .build()); System.out.printf( "%d mutate operations have been added so far.%n", response.getTotalOperations()); // You can use this next sequence token for calling addBatchJobOperations() next time. System.out.printf( "Next sequence token for adding next operations is '%s'.%n", response.getNextSequenceToken()); } /** * Requests the API to run the mutate job for executing all uploaded mutate job operations. * * @param batchJobServiceClient the mutate job service client. * @param batchJobResourceName the resource name of mutate job to be run. * @return the operation response from running mutate job. */ private OperationFuture runBatchJob( BatchJobServiceClient batchJobServiceClient, String batchJobResourceName) { OperationFuture operationResponse = batchJobServiceClient.runBatchJobAsync(batchJobResourceName); // BEWARE! The above call returns an OperationFuture. The execution of that future depends on // the thread pool which is owned by batchJobServiceClient. If you use this future, you *must* // keep the service client in scope too. // See https://developers.google.com/google-ads/api/docs/client-libs/java/lro for more detail. System.out.printf( "Mutate job with resource name '%s' has been executed.%n", batchJobResourceName); return operationResponse; } /** * Polls the server until the mutate job execution finishes by setting the total time to wait * before time-out. * * @param operationResponse the operation response used to poll the server. */ private void pollBatchJob(OperationFuture operationResponse) { try { operationResponse.get(MAX_TOTAL_POLL_INTERVAL_SECONDS, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { System.err.printf("Failed polling the mutate job. Exception: %s%n", e); System.exit(1); } } /** * Prints all the results from running the mutate job. * * @param batchJobServiceClient the mutate job service client. * @param batchJobResourceName the resource name of mutate job to get its results. */ private void fetchAndPrintResults( BatchJobServiceClient batchJobServiceClient, String batchJobResourceName) { System.out.printf( "Mutate job with resource name '%s' has finished. Now, printing its results...%n", batchJobResourceName); // Gets all the results from running mutate job and prints their information. ListBatchJobResultsPagedResponse batchJobResults = batchJobServiceClient.listBatchJobResults( ListBatchJobResultsRequest.newBuilder() .setResourceName(batchJobResourceName) .setPageSize(PAGE_SIZE) .build()); for (BatchJobResult batchJobResult : batchJobResults.iterateAll()) { System.out.printf( "Mutate job #%d has a status '%s' and response of type '%s'.%n", batchJobResult.getOperationIndex(), batchJobResult.getStatus().getMessage().isEmpty() ? "N/A" : batchJobResult.getStatus().getMessage(), batchJobResult .getMutateOperationResponse() .getResponseCase() .equals(ResponseCase.RESPONSE_NOT_SET) ? "N/A" : batchJobResult.getMutateOperationResponse().getResponseCase()); } } /** * Builds all operations for creating a complete campaign and return an array of their * corresponding mutate operations. * * @param customerId the client customer ID. * @return the mutate operations to be added to a mutate job. */ private List<MutateOperation> buildAllOperations(long customerId) { List<MutateOperation> mutateOperations = new ArrayList<>(); // Creates a new campaign budget operation and adds it to the array of mutate operations. CampaignBudgetOperation campaignBudgetOperation = buildCampaignBudgetOperation(customerId); mutateOperations.add( MutateOperation.newBuilder().setCampaignBudgetOperation(campaignBudgetOperation).build()); // Creates new campaign operations and adds them to the array of mutate operations. List<CampaignOperation> campaignOperations = buildCampaignOperations(customerId, campaignBudgetOperation.getCreate().getResourceName()); for (CampaignOperation campaignOperation : campaignOperations) { mutateOperations.add( MutateOperation.newBuilder().setCampaignOperation(campaignOperation).build()); } // Creates new campaign criterion operations and adds them to the array of mutate operations. List<CampaignCriterionOperation> campaignCriterionOperations = buildCampaignCriterionOperations(campaignOperations); for (CampaignCriterionOperation campaignCriterionOperation : campaignCriterionOperations) { mutateOperations.add( MutateOperation.newBuilder() .setCampaignCriterionOperation(campaignCriterionOperation) .build()); } // Creates new ad group operations and adds them to the array of mutate operations. List<AdGroupOperation> adGroupOperations = buildAdGroupOperations(customerId, campaignOperations); for (AdGroupOperation adGroupOperation : adGroupOperations) { mutateOperations.add( MutateOperation.newBuilder().setAdGroupOperation(adGroupOperation).build()); } // Creates new ad group criterion operations and adds them to the array of mutate operations. List<AdGroupCriterionOperation> adGroupCriterionOperations = buildAdGroupCriterionOperations(adGroupOperations); for (AdGroupCriterionOperation adGroupCriterionOperation : adGroupCriterionOperations) { mutateOperations.add( MutateOperation.newBuilder() .setAdGroupCriterionOperation(adGroupCriterionOperation) .build()); } // Creates new ad group ad operations and adds them to the array of mutate operations. List<AdGroupAdOperation> adGroupAdOperations = buildAdGroupAdOperations(adGroupOperations); for (AdGroupAdOperation adGroupAdOperation : adGroupAdOperations) { mutateOperations.add( MutateOperation.newBuilder().setAdGroupAdOperation(adGroupAdOperation).build()); } return mutateOperations; } /** * Builds a new campaign budget operation for the specified customer ID. * * @param customerId the client customer ID. * @return the campaign budget operation. */ private CampaignBudgetOperation buildCampaignBudgetOperation(long customerId) { // Creates a campaign budget. CampaignBudget budget = CampaignBudget.newBuilder() // Creates a resource name using the temporary ID. .setResourceName(ResourceNames.campaignBudget(customerId, getNextTemporaryId())) .setName("Interplanetary Cruise Budget #" + getPrintableDateTime()) .setDeliveryMethod(BudgetDeliveryMethod.STANDARD) .setAmountMicros(5_000_000) .build(); // Creates a campaign budget operation. return CampaignBudgetOperation.newBuilder().setCreate(budget).build(); } /** * Builds new campaign operations for the specified customer ID. * * @param customerId the client customer ID. * @param campaignBudgetResourceName the resource name of campaign budget to be used to create * campaigns. * @return the campaign operations. */ private List<CampaignOperation> buildCampaignOperations( long customerId, String campaignBudgetResourceName) { List<CampaignOperation> operations = new ArrayList<>(); for (int i = 0; i < NUMBER_OF_CAMPAIGNS_TO_ADD; i++) { // Creates a campaign. long campaignId = getNextTemporaryId(); Campaign campaign = Campaign.newBuilder() // Creates a resource name using the temporary ID. .setResourceName(ResourceNames.campaign(customerId, campaignId)) .setName("Mutate job campaign #" + getPrintableDateTime() + "." + campaignId) .setAdvertisingChannelType(AdvertisingChannelType.SEARCH) // Recommendation: Set the campaign to PAUSED when creating it to prevent // the ads from immediately serving. Set to ENABLED once you've added // targeting and the ads are ready to serve. .setStatus(CampaignStatus.PAUSED) // Sets the bidding strategy and budget. .setManualCpc(ManualCpc.newBuilder().build()) .setCampaignBudget(campaignBudgetResourceName) .build(); // Creates a campaign operation and adds it to the operations list. CampaignOperation op = CampaignOperation.newBuilder().setCreate(campaign).build(); operations.add(op); } return operations; } /** * Builds new campaign criterion operations for creating negative campaign criteria (as keywords). * * @param campaignOperations the campaign operations to be used to create campaign criteria. * @return the campaign criterion operations. */ private List<CampaignCriterionOperation> buildCampaignCriterionOperations( List<CampaignOperation> campaignOperations) { List<CampaignCriterionOperation> operations = new ArrayList<>(); for (CampaignOperation campaignOperation : campaignOperations) { // Creates a campaign criterion. CampaignCriterion campaignCriterion = CampaignCriterion.newBuilder() .setKeyword( KeywordInfo.newBuilder() .setText("venus") .setMatchType(KeywordMatchType.BROAD) .build()) // Sets the campaign criterion as a negative criterion. .setNegative(Boolean.TRUE) .setCampaign(campaignOperation.getCreate().getResourceName()) .build(); // Creates a campaign criterion operation and adds it to the operations list. CampaignCriterionOperation op = CampaignCriterionOperation.newBuilder().setCreate(campaignCriterion).build(); operations.add(op); } return operations; } /** * Builds new ad group operations for the specified customer ID. * * @param customerId the client customer ID. * @param campaignOperations the campaign operations to be used to create ad groups. * @return the ad group operations. */ private List<AdGroupOperation> buildAdGroupOperations( long customerId, List<CampaignOperation> campaignOperations) { List<AdGroupOperation> operations = new ArrayList<>(); for (CampaignOperation campaignOperation : campaignOperations) { for (int i = 0; i < NUMBER_OF_AD_GROUPS_TO_ADD; i++) { // Creates an ad group. long adGroupId = getNextTemporaryId(); AdGroup adGroup = AdGroup.newBuilder() // Creates a resource name using the temporary ID. .setResourceName(ResourceNames.adGroup(customerId, adGroupId)) .setName("Mutate job ad group #" + getPrintableDateTime() + "." + adGroupId) .setCampaign(campaignOperation.getCreate().getResourceName()) .setType(AdGroupType.SEARCH_STANDARD) .setCpcBidMicros(10_000_000) .build(); // Creates an ad group operation and adds it to the operations list. AdGroupOperation op = AdGroupOperation.newBuilder().setCreate(adGroup).build(); operations.add(op); } } return operations; } /** * Builds new ad group criterion operations for creating keywords. 50% of keywords are created * with some invalid characters to demonstrate how BatchJobService returns information about such * errors. * * @param adGroupOperations the ad group operations to be used to create ad group criteria. * @return the ad group criterion operations. */ private List<AdGroupCriterionOperation> buildAdGroupCriterionOperations( List<AdGroupOperation> adGroupOperations) { List<AdGroupCriterionOperation> operations = new ArrayList<>(); for (AdGroupOperation adGroupOperation : adGroupOperations) { for (int i = 0; i < NUMBER_OF_KEYWORDS_TO_ADD; i++) { // Creates a keyword text by making 50% of keywords invalid to demonstrate error handling. String keywordText = "mars" + i; if (i % 2 == 0) { keywordText += "!!!"; } // Creates an ad group criterion using the created keyword text. AdGroupCriterion adGroupCriterion = AdGroupCriterion.newBuilder() .setKeyword( KeywordInfo.newBuilder() .setText(keywordText) .setMatchType(KeywordMatchType.BROAD) .build()) .setAdGroup(adGroupOperation.getCreate().getResourceName()) .setStatus(AdGroupCriterionStatus.ENABLED) .build(); // Creates an ad group criterion operation and adds it to the operations list. AdGroupCriterionOperation op = AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterion).build(); operations.add(op); } } return operations; } /** * Builds new ad group ad operations. * * @param adGroupOperations the ad group operations to be used to create ad group ads. * @return the ad group ad operations. */ private List<AdGroupAdOperation> buildAdGroupAdOperations( List<AdGroupOperation> adGroupOperations) { List<AdGroupAdOperation> operations = new ArrayList<>(); for (AdGroupOperation adGroupOperation : adGroupOperations) { // Creates an ad group ad. AdGroupAd adGroupAd = AdGroupAd.newBuilder() // Creates the expanded text ad info. .setAd( Ad.newBuilder() // Sets the expanded text ad info on an ad. .setExpandedTextAd( ExpandedTextAdInfo.newBuilder() .setHeadlinePart1("Cruise to Mars #" + getPrintableDateTime()) .setHeadlinePart2("Best Space Cruise Line") .setDescription("Buy your tickets now!") .build()) .addFinalUrls("http://www.example.com") .build()) .setAdGroup(adGroupOperation.getCreate().getResourceName()) .setStatus(AdGroupAdStatus.PAUSED) .build(); // Creates an ad group ad operation and adds it to the operations list. AdGroupAdOperation op = AdGroupAdOperation.newBuilder().setCreate(adGroupAd).build(); operations.add(op); } return operations; } /** * Returns the next temporary ID and decreases it by one. * * @return the next temporary ID. */ private long getNextTemporaryId() { return temporaryId--; } }
C#
// Copyright 2020 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.GoogleAds.Lib; using Google.Ads.GoogleAds.V17.Common; using Google.Ads.GoogleAds.V17.Errors; using Google.Ads.GoogleAds.V17.Resources; using Google.Ads.GoogleAds.V17.Services; using Google.Api.Gax; using Google.LongRunning; using Google.Protobuf.WellKnownTypes; using System; using System.Collections.Generic; using static Google.Ads.GoogleAds.V17.Enums.AdGroupAdStatusEnum.Types; using static Google.Ads.GoogleAds.V17.Enums.AdGroupCriterionStatusEnum.Types; using static Google.Ads.GoogleAds.V17.Enums.AdGroupTypeEnum.Types; using static Google.Ads.GoogleAds.V17.Enums.AdvertisingChannelTypeEnum.Types; using static Google.Ads.GoogleAds.V17.Enums.BudgetDeliveryMethodEnum.Types; using static Google.Ads.GoogleAds.V17.Enums.CampaignStatusEnum.Types; using static Google.Ads.GoogleAds.V17.Enums.KeywordMatchTypeEnum.Types; using static Google.Ads.GoogleAds.V17.Resources.BatchJob.Types; namespace Google.Ads.GoogleAds.Examples.V17 { /// <summary> /// This code example adds complete campaigns including campaign budgets, campaigns, ad groups /// and keywords using BatchJobService. /// </summary> public class AddCompleteCampaignsUsingBatchJob : ExampleBase { /// <summary> /// Command line options for running the <see cref="AddCompleteCampaignsUsingBatchJob"/> /// example. /// </summary> public class Options : OptionsBase { /// <summary> /// The Google Ads customer ID for which the call is made. /// </summary> [Option("customerId", Required = true, HelpText = "The Google Ads customer ID for which the call is made.")] public long CustomerId { 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); AddCompleteCampaignsUsingBatchJob codeExample = new AddCompleteCampaignsUsingBatchJob(); Console.WriteLine(codeExample.Description); codeExample.Run(new GoogleAdsClient(), options.CustomerId); } /// <summary> /// The number of campaigns to add. /// </summary> private const int NUMBER_OF_CAMPAIGNS_TO_ADD = 2; /// <summary> /// The number of ad groups per campaign to add. /// </summary> private const int NUMBER_OF_AD_GROUPS_TO_ADD = 2; /// <summary> /// The number of keywords per ad group to add. /// </summary> private const int NUMBER_OF_KEYWORDS_TO_ADD = 4; /// <summary> /// The maximum total poll interval in seconds. /// </summary> private const int MAX_TOTAL_POLL_INTERVAL_SECONDS = 60; /// <summary> /// The page size for retrieving results. /// </summary> private const int PAGE_SIZE = 1000; /// <summary> /// The negative temporary ID used in batch job operations. /// </summary> private static long temporaryId = -1; /// <summary> /// Returns a description about the code example. /// </summary> public override string Description => "This code example adds complete campaigns including campaign budgets, campaigns, " + "ad groups and keywords using BatchJobService."; /// <summary> /// Runs the code example. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> public void Run(GoogleAdsClient client, long customerId) { // Gets the BatchJobService. BatchJobServiceClient batchJobService = client.GetService(Services.V17.BatchJobService); try { string batchJobResourceName = CreateBatchJob(batchJobService, customerId); AddAllBatchJobOperations(batchJobService, customerId, batchJobResourceName); Operation<Empty, BatchJobMetadata> operationResponse = RunBatchJob(batchJobService, batchJobResourceName); PollBatchJob(operationResponse); FetchAndPrintResults(batchJobService, batchJobResourceName); } 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 the batch job. /// </summary> /// <param name="batchJobService">The batch job service.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <returns>The resource name of the created batch job.</returns> private static string CreateBatchJob(BatchJobServiceClient batchJobService, long customerId) { BatchJobOperation operation = new BatchJobOperation() { Create = new BatchJob() { } }; string batchJobResourceName = batchJobService.MutateBatchJob(customerId.ToString(), operation) .Result.ResourceName; Console.WriteLine($"Created a batch job with resource name: " + $"'{batchJobResourceName}'."); return batchJobResourceName; } /// <summary> /// Adds all batch job operations to the batch job. As this is the first time for this /// batch job, the sequence token is not set. The response will contain the next sequence /// token that you can use to upload more operations in the future. /// </summary> /// <param name="batchJobService">The batch job service.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="batchJobResourceName">The resource name of batch job to which the batch /// job operations will be added. /// </param> private static void AddAllBatchJobOperations(BatchJobServiceClient batchJobService, long customerId, string batchJobResourceName) { AddBatchJobOperationsResponse response = batchJobService.AddBatchJobOperations( new AddBatchJobOperationsRequest() { ResourceName = batchJobResourceName, MutateOperations = { BuildAllOperations(customerId) } }); Console.WriteLine($"{response.TotalOperations} mutate operations have been added" + $" so far."); // You can use this next sequence token for calling AddBatchJobOperations() next time. Console.WriteLine($"Next sequence token for adding next operations is " + $"'{response.NextSequenceToken}'."); } /// <summary> /// Requests the API to run the batch job for executing all uploaded batch job /// operations. /// </summary> /// <param name="batchJobService">The batch job service client.</param> /// <param name="batchJobResourceName">The resource name of batch job to be run.</param> /// <returns>The operation response from running batch job.</returns> private Operation<Empty, BatchJobMetadata> RunBatchJob( BatchJobServiceClient batchJobService, string batchJobResourceName) { Operation<Empty, BatchJobMetadata> operationResponse = batchJobService.RunBatchJob(batchJobResourceName); Console.WriteLine($"Batch job with resource name '{batchJobResourceName}' has been " + $"executed."); return operationResponse; } /// <summary> /// Polls the server until the batch job execution finishes by setting the total /// time to wait before time-out. /// </summary> /// <param name="operationResponse">The operation response used to poll the server.</param> private static void PollBatchJob(Operation<Empty, BatchJobMetadata> operationResponse) { PollSettings pollSettings = new PollSettings( Expiration.FromTimeout(TimeSpan.FromSeconds(MAX_TOTAL_POLL_INTERVAL_SECONDS)), TimeSpan.FromSeconds(1)); operationResponse.PollUntilCompleted(pollSettings); } /// <summary> /// Fetches and prints all the results from running the batch job. /// </summary> /// <param name="batchJobService">The batch job service.</param> /// <param name="batchJobResourceName">The resource name of batch job to get its results. /// </param> private static void FetchAndPrintResults(BatchJobServiceClient batchJobService, string batchJobResourceName) { Console.WriteLine($"batch job with resource name '{batchJobResourceName}' has " + $"finished. Now, printing its results..."); ListBatchJobResultsRequest request = new ListBatchJobResultsRequest() { ResourceName = batchJobResourceName, PageSize = PAGE_SIZE, }; ListBatchJobResultsResponse resp = new ListBatchJobResultsResponse(); // Gets all the results from running batch job and prints their information. foreach (BatchJobResult batchJobResult in batchJobService.ListBatchJobResults(request)) { if (!batchJobResult.IsFailed) { Console.WriteLine($"batch job result #{batchJobResult.OperationIndex} is " + $"successful and response is of type " + $"'{batchJobResult.MutateOperationResponse.ResponseCase}'."); } else { Console.WriteLine($"batch job result #{batchJobResult.OperationIndex} " + $"failed with error message {batchJobResult.Status.Message}."); foreach (GoogleAdsError error in batchJobResult.Failure.Errors) { Console.WriteLine($"Error found: {error}."); } } } } /// <summary> /// Builds all operations for creating a complete campaign and return an array of /// their corresponding mutate operations. /// </summary> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <returns>The mutate operations to be added to a batch job.</returns> private static List<MutateOperation> BuildAllOperations(long customerId) { List<MutateOperation> mutateOperations = new List<MutateOperation>(); // Creates a new campaign budget operation and adds it to the array of mutate operations. CampaignBudgetOperation campaignBudgetOperation = BuildCampaignBudgetOperation(customerId); mutateOperations.Add( new MutateOperation() { CampaignBudgetOperation = campaignBudgetOperation } ); // Creates new campaign operations and adds them to the array of mutate operations. List<CampaignOperation> campaignOperations = BuildCampaignOperations(customerId, campaignBudgetOperation.Create.ResourceName); foreach (CampaignOperation campaignOperation in campaignOperations) { mutateOperations.Add( new MutateOperation() { CampaignOperation = campaignOperation } ); } // Creates new campaign criterion operations and adds them to the array of mutate // operations. List<CampaignCriterionOperation> campaignCriterionOperations = BuildCampaignCriterionOperations(campaignOperations); foreach (CampaignCriterionOperation campaignCriterionOperation in campaignCriterionOperations) { mutateOperations.Add( new MutateOperation() { CampaignCriterionOperation = campaignCriterionOperation } ); } // Creates new ad group operations and adds them to the array of mutate operations. List<AdGroupOperation> adGroupOperations = BuildAdGroupOperations(customerId, campaignOperations); foreach (AdGroupOperation adGroupOperation in adGroupOperations) { mutateOperations.Add( new MutateOperation() { AdGroupOperation = adGroupOperation } ); } // Creates new ad group criterion operations and adds them to the array of mutate // operations. List<AdGroupCriterionOperation> adGroupCriterionOperations = BuildAdGroupCriterionOperations(adGroupOperations); foreach (AdGroupCriterionOperation adGroupCriterionOperation in adGroupCriterionOperations) { mutateOperations.Add( new MutateOperation() { AdGroupCriterionOperation = adGroupCriterionOperation } ); } // Creates new ad group ad operations and adds them to the array of mutate operations. List<AdGroupAdOperation> adGroupAdOperations = BuildAdGroupAdOperations(adGroupOperations); foreach (AdGroupAdOperation adGroupAdOperation in adGroupAdOperations) { mutateOperations.Add( new MutateOperation() { AdGroupAdOperation = adGroupAdOperation } ); } return mutateOperations; } /// <summary> /// Builds a new campaign budget operation for the specified customer ID. /// </summary> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <returns>The campaign budget operation.</returns> private static CampaignBudgetOperation BuildCampaignBudgetOperation(long customerId) { // Creates a campaign budget. CampaignBudget budget = new CampaignBudget() { ResourceName = ResourceNames.CampaignBudget(customerId, GetNextTemporaryId()), Name = "batch job Budget #" + ExampleUtilities.GetRandomString(), DeliveryMethod = BudgetDeliveryMethod.Standard, AmountMicros = 5_000_000 }; // Creates a campaign budget operation. return new CampaignBudgetOperation() { Create = budget }; } /// <summary> /// Builds new campaign operations for the specified customer ID. /// </summary> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="campaignBudgetResourceName">The resource name of campaign budget to be /// used to create campaigns.</param> /// <returns>The campaign operations.</returns> private static List<CampaignOperation> BuildCampaignOperations(long customerId, string campaignBudgetResourceName) { List<CampaignOperation> operations = new List<CampaignOperation>(); for (int i = 0; i < NUMBER_OF_CAMPAIGNS_TO_ADD; i++) { // Creates a campaign. long campaignId = GetNextTemporaryId(); Campaign campaign = new Campaign() { ResourceName = ResourceNames.Campaign(customerId, campaignId), Name = "batch job campaign #" + ExampleUtilities.GetRandomString(), AdvertisingChannelType = AdvertisingChannelType.Search, // Recommendation: Set the campaign to PAUSED when creating it to prevent // the ads from immediately serving. Set to ENABLED once you've added // targeting and the ads are ready to serve. Status = CampaignStatus.Paused, // Sets the bidding strategy and budget. ManualCpc = new ManualCpc(), CampaignBudget = campaignBudgetResourceName }; // Creates a campaign operation and adds it to the operations list. CampaignOperation op = new CampaignOperation() { Create = campaign }; operations.Add(op); } return operations; } /// <summary> /// Builds new campaign criterion operations for creating negative campaign criteria /// (as keywords). /// </summary> /// <param name="campaignOperations">The campaign operations to be used to create /// campaign criteria.</param> /// <returns>The campaign criterion operations.</returns> private static List<CampaignCriterionOperation> BuildCampaignCriterionOperations( List<CampaignOperation> campaignOperations) { List<CampaignCriterionOperation> operations = new List<CampaignCriterionOperation>(); foreach (CampaignOperation campaignOperation in campaignOperations) { // Creates a campaign criterion. CampaignCriterion campaignCriterion = new CampaignCriterion() { Keyword = new KeywordInfo() { Text = "venus", MatchType = KeywordMatchType.Broad }, // Sets the campaign criterion as a negative criterion. Negative = true, Campaign = campaignOperation.Create.ResourceName }; // Creates a campaign criterion operation and adds it to the operations list. CampaignCriterionOperation op = new CampaignCriterionOperation() { Create = campaignCriterion }; operations.Add(op); } return operations; } /// <summary> /// Builds new ad group operations for the specified customer ID. /// </summary> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="campaignOperations">The campaign operations to be used to create ad /// groups.</param> /// <returns>The ad group operations.</returns> private static List<AdGroupOperation> BuildAdGroupOperations( long customerId, List<CampaignOperation> campaignOperations) { List<AdGroupOperation> operations = new List<AdGroupOperation>(); foreach (CampaignOperation campaignOperation in campaignOperations) { for (int i = 0; i < NUMBER_OF_AD_GROUPS_TO_ADD; i++) { // Creates an ad group. long adGroupId = GetNextTemporaryId(); AdGroup adGroup = new AdGroup() { ResourceName = ResourceNames.AdGroup(customerId, adGroupId), Name = "batch job ad group #" + ExampleUtilities.GetShortRandomString(), Campaign = campaignOperation.Create.ResourceName, Type = AdGroupType.SearchStandard, CpcBidMicros = 10_000_000 }; // Creates an ad group operation and adds it to the operations list. AdGroupOperation op = new AdGroupOperation() { Create = adGroup }; operations.Add(op); } } return operations; } /// <summary> /// Builds new ad group criterion operations for creating keywords. 50% of keywords are /// created some invalid characters to demonstrate how BatchJobService returns information /// about such errors. /// </summary> /// <param name="adGroupOperations">The ad group operations to be used to create ad group /// criteria.</param> /// <returns>The ad group criterion operations.</returns> private static List<AdGroupCriterionOperation> BuildAdGroupCriterionOperations( List<AdGroupOperation> adGroupOperations) { List<AdGroupCriterionOperation> operations = new List<AdGroupCriterionOperation>(); foreach (AdGroupOperation adGroupOperation in adGroupOperations) { for (int i = 0; i < NUMBER_OF_KEYWORDS_TO_ADD; i++) { // Creates a keyword text by making 50% of keywords invalid to demonstrate // error handling. string keywordText = "mars" + i; if (i % 2 == 0) { keywordText += "!!!"; } // Creates an ad group criterion using the created keyword text. AdGroupCriterion adGroupCriterion = new AdGroupCriterion() { Keyword = new KeywordInfo() { Text = keywordText, MatchType = KeywordMatchType.Broad, }, AdGroup = adGroupOperation.Create.ResourceName, Status = AdGroupCriterionStatus.Paused }; // Creates an ad group criterion operation and adds it to the operations list. AdGroupCriterionOperation op = new AdGroupCriterionOperation() { Create = adGroupCriterion }; operations.Add(op); } } return operations; } /// <summary> /// Builds the ad group ad operations. /// </summary> /// <param name="adGroupOperations">The ad group operations to be used to create ad /// group ads.</param> /// <returns>The ad group ad operations.</returns> private static List<AdGroupAdOperation> BuildAdGroupAdOperations( List<AdGroupOperation> adGroupOperations) { List<AdGroupAdOperation> operations = new List<AdGroupAdOperation>(); foreach (AdGroupOperation adGroupOperation in adGroupOperations) { // Creates an ad group ad. AdGroupAd adGroupAd = new AdGroupAd() { Ad = new Ad { FinalUrls = { "http://www.example.com/" }, // Sets the expanded text ad info on an ad. ExpandedTextAd = new ExpandedTextAdInfo { HeadlinePart1 = "Cruise #" + ExampleUtilities.GetShortRandomString() + " to Mars", HeadlinePart2 = "Best Space Cruise Line", Description = "Buy your tickets now!", }, }, AdGroup = adGroupOperation.Create.ResourceName, // Optional: Set the status. Status = AdGroupAdStatus.Paused, }; // Creates an ad group ad operation and adds it to the operations list. AdGroupAdOperation op = new AdGroupAdOperation() { Create = adGroupAd }; operations.Add(op); } return operations; } /// <summary> /// Returns the next temporary ID and decreases it by one. /// </summary> /// <returns>The next temporary ID.</returns> private static long GetNextTemporaryId() { return temporaryId--; } } }
PHP
<?php /** * Copyright 2019 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\CampaignManagement; 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\V17\GoogleAdsClient; use Google\Ads\GoogleAds\Lib\V17\GoogleAdsClientBuilder; use Google\Ads\GoogleAds\Lib\V17\GoogleAdsException; use Google\Ads\GoogleAds\Util\V17\ResourceNames; use Google\Ads\GoogleAds\V17\Common\ExpandedTextAdInfo; use Google\Ads\GoogleAds\V17\Common\KeywordInfo; use Google\Ads\GoogleAds\V17\Common\ManualCpc; use Google\Ads\GoogleAds\V17\Enums\AdGroupAdStatusEnum\AdGroupAdStatus; use Google\Ads\GoogleAds\V17\Enums\AdGroupCriterionStatusEnum\AdGroupCriterionStatus; use Google\Ads\GoogleAds\V17\Enums\AdGroupTypeEnum\AdGroupType; use Google\Ads\GoogleAds\V17\Enums\AdvertisingChannelTypeEnum\AdvertisingChannelType; use Google\Ads\GoogleAds\V17\Enums\BudgetDeliveryMethodEnum\BudgetDeliveryMethod; use Google\Ads\GoogleAds\V17\Enums\CampaignStatusEnum\CampaignStatus; use Google\Ads\GoogleAds\V17\Enums\KeywordMatchTypeEnum\KeywordMatchType; use Google\Ads\GoogleAds\V17\Errors\GoogleAdsError; use Google\Ads\GoogleAds\V17\Resources\Ad; use Google\Ads\GoogleAds\V17\Resources\AdGroup; use Google\Ads\GoogleAds\V17\Resources\AdGroupAd; use Google\Ads\GoogleAds\V17\Resources\AdGroupCriterion; use Google\Ads\GoogleAds\V17\Resources\BatchJob; use Google\Ads\GoogleAds\V17\Resources\Campaign; use Google\Ads\GoogleAds\V17\Resources\CampaignBudget; use Google\Ads\GoogleAds\V17\Resources\CampaignCriterion; use Google\Ads\GoogleAds\V17\Services\AddBatchJobOperationsRequest; use Google\Ads\GoogleAds\V17\Services\AdGroupAdOperation; use Google\Ads\GoogleAds\V17\Services\AdGroupCriterionOperation; use Google\Ads\GoogleAds\V17\Services\AdGroupOperation; use Google\Ads\GoogleAds\V17\Services\BatchJobOperation; use Google\Ads\GoogleAds\V17\Services\BatchJobResult; use Google\Ads\GoogleAds\V17\Services\CampaignBudgetOperation; use Google\Ads\GoogleAds\V17\Services\CampaignCriterionOperation; use Google\Ads\GoogleAds\V17\Services\CampaignOperation; use Google\Ads\GoogleAds\V17\Services\Client\BatchJobServiceClient; use Google\Ads\GoogleAds\V17\Services\ListBatchJobResultsRequest; use Google\Ads\GoogleAds\V17\Services\MutateBatchJobRequest; use Google\Ads\GoogleAds\V17\Services\MutateOperation; use Google\Ads\GoogleAds\V17\Services\RunBatchJobRequest; use Google\ApiCore\ApiException; use Google\ApiCore\OperationResponse; /** * This example adds complete campaigns including campaign budgets, campaigns, ad groups and * keywords using BatchJobService. */ class AddCompleteCampaignsUsingBatchJob { private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE'; private const NUMBER_OF_CAMPAIGNS_TO_ADD = 2; private const NUMBER_OF_AD_GROUPS_TO_ADD = 2; private const NUMBER_OF_KEYWORDS_TO_ADD = 4; private const POLL_FREQUENCY_SECONDS = 1; private const MAX_TOTAL_POLL_INTERVAL_SECONDS = 60; private const PAGE_SIZE = 1000; /** @var int the negative temporary ID used in batch job operations. */ private static $temporaryId = -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, ]); // 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 ); } 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 */ public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId) { $batchJobServiceClient = $googleAdsClient->getBatchJobServiceClient(); $batchJobResourceName = self::createBatchJob($batchJobServiceClient, $customerId); self::addAllBatchJobOperations( $batchJobServiceClient, $customerId, $batchJobResourceName ); $operationResponse = self::runBatchJob($batchJobServiceClient, $batchJobResourceName); self::pollBatchJob($operationResponse); self::fetchAndPrintResults($batchJobServiceClient, $batchJobResourceName); } /** * Creates a new batch job for the specified customer ID. * * @param BatchJobServiceClient $batchJobServiceClient the batch job service client * @param int $customerId the customer ID * @return string the resource name of the created batch job */ private static function createBatchJob( BatchJobServiceClient $batchJobServiceClient, int $customerId ): string { // Creates a batch job operation to create a new batch job. $batchJobOperation = new BatchJobOperation(); $batchJobOperation->setCreate(new BatchJob()); // Issues a request to the API and get the batch job's resource name. $batchJobResourceName = $batchJobServiceClient->mutateBatchJob( MutateBatchJobRequest::build($customerId, $batchJobOperation) )->getResult()->getResourceName(); printf( "Created a batch job with resource name: '%s'.%s", $batchJobResourceName, PHP_EOL ); return $batchJobResourceName; } /** * Adds all batch job operations to the batch job. As this is the first time for this * batch job, pass null as a sequence token. The response will contain the next sequence token * that you can use to upload more operations in the future. * * @param BatchJobServiceClient $batchJobServiceClient the batch job service client * @param int $customerId the customer ID * @param string $batchJobResourceName the resource name of batch job to which the batch job * operations will be added */ private static function addAllBatchJobOperations( BatchJobServiceClient $batchJobServiceClient, int $customerId, string $batchJobResourceName ): void { $response = $batchJobServiceClient->addBatchJobOperations( AddBatchJobOperationsRequest::build( $batchJobResourceName, '', self::buildAllOperations($customerId) ) ); printf( "%d mutate operations have been added so far.%s", $response->getTotalOperations(), PHP_EOL ); // You can use this next sequence token for calling addBatchJobOperations() next time. printf( "Next sequence token for adding next operations is '%s'.%s", $response->getNextSequenceToken(), PHP_EOL ); } /** * Requests the API to run the batch job for executing all uploaded batch job operations. * * @param BatchJobServiceClient $batchJobServiceClient the batch job service client * @param string $batchJobResourceName the resource name of batch job to be run * @return OperationResponse the operation response from running batch job */ private static function runBatchJob( BatchJobServiceClient $batchJobServiceClient, string $batchJobResourceName ): OperationResponse { $operationResponse = $batchJobServiceClient->runBatchJob(RunBatchJobRequest::build($batchJobResourceName)); printf( "Batch job with resource name '%s' has been executed.%s", $batchJobResourceName, PHP_EOL ); return $operationResponse; } /** * Polls the server until the batch job execution finishes by setting the initial poll * delay time and the total time to wait before time-out. * * @param OperationResponse $operationResponse the operation response used to poll the server */ private static function pollBatchJob(OperationResponse $operationResponse): void { $operationResponse->pollUntilComplete([ 'initialPollDelayMillis' => self::POLL_FREQUENCY_SECONDS * 1000, 'totalPollTimeoutMillis' => self::MAX_TOTAL_POLL_INTERVAL_SECONDS * 1000 ]); } /** * Prints all the results from running the batch job. * * @param BatchJobServiceClient $batchJobServiceClient the batch job service client * @param string $batchJobResourceName the resource name of batch job to get its results */ private static function fetchAndPrintResults( BatchJobServiceClient $batchJobServiceClient, string $batchJobResourceName ): void { printf( "Batch job with resource name '%s' has finished. Now, printing its results...%s", $batchJobResourceName, PHP_EOL ); // Gets all the results from running batch job and print their information. $batchJobResults = $batchJobServiceClient->listBatchJobResults( ListBatchJobResultsRequest::build($batchJobResourceName)->setPageSize(self::PAGE_SIZE) ); foreach ($batchJobResults->iterateAllElements() as $batchJobResult) { /** @var BatchJobResult $batchJobResult */ printf( "Batch job #%d has a status '%s' and response of type '%s'.%s", $batchJobResult->getOperationIndex(), $batchJobResult->getStatus() ? $batchJobResult->getStatus()->getMessage() : 'N/A', $batchJobResult->getMutateOperationResponse() ? $batchJobResult->getMutateOperationResponse()->getResponse() : 'N/A', PHP_EOL ); } } /** * Builds all operations for creating a complete campaign and return an array of their * corresponding mutate operations. * * @param int $customerId the customer ID * @return MutateOperation[] the mutate operations to be added to a batch job */ private static function buildAllOperations(int $customerId): array { $mutateOperations = []; // Creates a new campaign budget operation and add it to the array of mutate operations. $campaignBudgetOperation = self::buildCampaignBudgetOperation($customerId); $mutateOperations[] = new MutateOperation(['campaign_budget_operation' => $campaignBudgetOperation]); // Creates new campaign operations and adds them to the array of mutate operations. $campaignOperations = self::buildCampaignOperations( $customerId, $campaignBudgetOperation->getCreate()->getResourceName() ); $mutateOperations = array_merge($mutateOperations, array_map( function (CampaignOperation $campaignOperation) { return new MutateOperation(['campaign_operation' => $campaignOperation]); }, $campaignOperations )); // Creates new campaign criterion operations and adds them to the array of mutate // operations. $mutateOperations = array_merge($mutateOperations, array_map( function (CampaignCriterionOperation $campaignCriterionOperation) { return new MutateOperation( ['campaign_criterion_operation' => $campaignCriterionOperation] ); }, self::buildCampaignCriterionOperations($campaignOperations) )); // Creates new ad group operations and adds them to the array of mutate operations. $adGroupOperations = self::buildAdGroupOperations($customerId, $campaignOperations); $mutateOperations = array_merge($mutateOperations, array_map( function (AdGroupOperation $adGroupOperation) { return new MutateOperation(['ad_group_operation' => $adGroupOperation]); }, $adGroupOperations )); // Creates new ad group criterion operations and adds them to the array of mutate // operations. $mutateOperations = array_merge($mutateOperations, array_map( function (AdGroupCriterionOperation $adGroupCriterionOperation) { return new MutateOperation( ['ad_group_criterion_operation' => $adGroupCriterionOperation] ); }, self::buildAdGroupCriterionOperations($adGroupOperations) )); // Creates new ad group ad operations and adds them to the array of mutate operations. $mutateOperations = array_merge($mutateOperations, array_map( function (AdGroupAdOperation $adGroupAdOperation) { return new MutateOperation(['ad_group_ad_operation' => $adGroupAdOperation]); }, self::buildAdGroupAdOperations($adGroupOperations) )); return $mutateOperations; } /** * Builds a new campaign budget operation for the specified customer ID. * * @param int $customerId the customer ID * @return CampaignBudgetOperation the campaign budget operation */ private static function buildCampaignBudgetOperation(int $customerId): CampaignBudgetOperation { // Creates a campaign budget operation. return new CampaignBudgetOperation([ 'create' => new CampaignBudget([ // Creates a resource name using the temporary ID. 'resource_name' => ResourceNames::forCampaignBudget( $customerId, self::getNextTemporaryId() ), 'name' => 'Interplanetary Cruise Budget #' . Helper::getPrintableDatetime(), 'delivery_method' => BudgetDeliveryMethod::STANDARD, 'amount_micros' => 5000000 ]) ]); } /** * Builds new campaign operations for the specified customer ID. * * @param int $customerId the customer ID * @param string $campaignBudgetResourceName the resource name of campaign budget to be used * to create campaigns * @return CampaignOperation[] the campaign operations */ private static function buildCampaignOperations( int $customerId, string $campaignBudgetResourceName ): array { $operations = []; for ($i = 0; $i < self::NUMBER_OF_CAMPAIGNS_TO_ADD; $i++) { // Creates a campaign. $campaignId = self::getNextTemporaryId(); $campaign = new Campaign([ // Creates a resource name using the temporary ID. 'resource_name' => ResourceNames::forCampaign($customerId, $campaignId), 'name' => sprintf( 'Mutate job campaign #%s.%d', Helper::getPrintableDatetime(), $campaignId ), 'advertising_channel_type' => AdvertisingChannelType::SEARCH, // Recommendation: Set the campaign to PAUSED when creating it to prevent // the ads from immediately serving. Set to ENABLED once you've added // targeting and the ads are ready to serve. 'status' => CampaignStatus::PAUSED, // Sets the bidding strategy and budget. 'manual_cpc' => new ManualCpc(), 'campaign_budget' => $campaignBudgetResourceName, ]); // Creates a campaign operation and add it to the operations list. $operations[] = new CampaignOperation(['create' => $campaign]); } return $operations; } /** * Builds new campaign criterion operations for creating negative campaign criteria * (as keywords). * * @param CampaignOperation[] $campaignOperations the campaign operations to be used to create * campaign criteria * @return CampaignCriterionOperation[] the campaign criterion operations */ private static function buildCampaignCriterionOperations(array $campaignOperations): array { $operations = []; foreach ($campaignOperations as $campaignOperation) { // Creates a campaign criterion. $campaignCriterion = new CampaignCriterion([ 'keyword' => new KeywordInfo([ 'text' => 'venus', 'match_type' => KeywordMatchType::BROAD ]), // Sets the campaign criterion as a negative criterion. 'negative' => true, 'campaign' => $campaignOperation->getCreate()->getResourceName() ]); // Creates a campaign criterion operation and add it to the operations list. $operations[] = new CampaignCriterionOperation(['create' => $campaignCriterion]); } return $operations; } /** * Builds new ad group operations for the specified customer ID. * * @param int $customerId the customer ID * @param CampaignOperation[] $campaignOperations the campaign operations to be used to create * ad groups * @return AdGroupOperation[] the ad group operations */ private static function buildAdGroupOperations( int $customerId, array $campaignOperations ): array { $operations = []; foreach ($campaignOperations as $campaignOperation) { for ($i = 0; $i < self::NUMBER_OF_AD_GROUPS_TO_ADD; $i++) { // Creates an ad group. $adGroupId = self::getNextTemporaryId(); $adGroup = new AdGroup([ // Creates a resource name using the temporary ID. 'resource_name' => ResourceNames::forAdGroup($customerId, $adGroupId), 'name' => sprintf( 'Mutate job ad group #%s.%d', Helper::getPrintableDatetime(), $adGroupId ), 'campaign' => $campaignOperation->getCreate()->getResourceName(), 'type' => AdGroupType::SEARCH_STANDARD, 'cpc_bid_micros' => 10000000 ]); // Creates an ad group operation and add it to the operations list. $operations[] = new AdGroupOperation(['create' => $adGroup]); } } return $operations; } /** * Builds new ad group criterion operations for creating keywords. 50% of keywords are created * with some invalid characters to demonstrate how BatchJobService returns information about * such errors. * * @param AdGroupOperation[] $adGroupOperations the ad group operations to be used to create * ad group criteria * @return AdGroupCriterionOperation[] the ad group criterion operations */ private static function buildAdGroupCriterionOperations(array $adGroupOperations): array { $operations = []; foreach ($adGroupOperations as $adGroupOperation) { for ($i = 0; $i < self::NUMBER_OF_KEYWORDS_TO_ADD; $i++) { // Create a keyword text by making 50% of keywords invalid to demonstrate error // handling. $keywordText = sprintf('mars%d', $i); if ($i % 2 == 0) { $keywordText = $keywordText . '!!!'; } // Creates an ad group criterion using the created keyword text. $adGroupCriterion = new AdGroupCriterion([ 'keyword' => new KeywordInfo([ 'text' => $keywordText, 'match_type' => KeywordMatchType::BROAD ]), 'ad_group' => $adGroupOperation->getCreate()->getResourceName(), 'status' => AdGroupCriterionStatus::ENABLED, ]); // Creates an ad group criterion operation and add it to the operations list. $operations[] = new AdGroupCriterionOperation(['create' => $adGroupCriterion]); } } return $operations; } /** * Builds new ad group ad operations. * * @param AdGroupOperation[] $adGroupOperations the ad group operations to be used to create * ad group ads * @return AdGroupAdOperation[] the ad group ad operations */ private static function buildAdGroupAdOperations(array $adGroupOperations): array { $operations = []; foreach ($adGroupOperations as $adGroupOperation) { // Creates an ad group ad. $adGroupAd = new AdGroupAd([ // Creates the expanded text ad info. 'ad' => new Ad([ // Sets the expanded text ad info on an ad. 'expanded_text_ad' => new ExpandedTextAdInfo([ 'headline_part1' => 'Cruise to Mars #' . Helper::getPrintableDatetime(), 'headline_part2' => 'Best Space Cruise Line', 'description' => 'Buy your tickets now!' ]), 'final_urls' => ['http://www.example.com'] ]), 'ad_group' => $adGroupOperation->getCreate()->getResourceName(), 'status' => AdGroupAdStatus::PAUSED, ]); // Creates an ad group ad operation and add it to the operations list. $operations[] = new AdGroupAdOperation(['create' => $adGroupAd]); } return $operations; } /** * Returns the next temporary ID and decrease it by one. * * @return int the next temporary ID */ private static function getNextTemporaryId(): int { return self::$temporaryId--; } } AddCompleteCampaignsUsingBatchJob::main();
Python
#!/usr/bin/env python # Copyright 2020 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. """Adds complete campaigns using BatchJobService. Complete campaigns include campaign budgets, campaigns, ad groups and keywords. """ import argparse import asyncio import sys from uuid import uuid4 from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException NUMBER_OF_CAMPAIGNS_TO_ADD = 2 NUMBER_OF_AD_GROUPS_TO_ADD = 2 NUMBER_OF_KEYWORDS_TO_ADD = 4 _temporary_id = 0 def get_next_temporary_id(): """Returns the next temporary ID to use in batch job operations. Decrements the temporary ID by one before returning it. The first value returned for the ID is -1. Returns: an int of the next temporary ID. """ global _temporary_id _temporary_id -= 1 return _temporary_id def build_mutate_operation(client, operation_type, operation): """Builds a mutate operation with the given operation type and operation. Args: client: an initialized GoogleAdsClient instance. operation_type: a str of the operation type corresponding to a field on the MutateOperation message class. operation: an operation instance. Returns: a MutateOperation instance """ mutate_operation = client.get_type("MutateOperation") # Retrieve the nested operation message instance using getattr then copy the # contents of the given operation into it using the client.copy_from method. client.copy_from(getattr(mutate_operation, operation_type), operation) return mutate_operation async def main(client, customer_id): """Main function that runs the example. Args: client: an initialized GoogleAdsClient instance. customer_id: a str of a customer ID. """ batch_job_service = client.get_service("BatchJobService") batch_job_operation = create_batch_job_operation(client) resource_name = create_batch_job( batch_job_service, customer_id, batch_job_operation ) operations = build_all_operations(client, customer_id) add_all_batch_job_operations(batch_job_service, operations, resource_name) operations_response = run_batch_job(batch_job_service, resource_name) # Create an asyncio.Event instance to control execution during the # asynchronous steps in _poll_batch_job. Note that this is not important # for polling asynchronously, it simply helps with execution control, so we # can run _fetch_and_print_results after the asynchronous operations have # completed. done_event = asyncio.Event() poll_batch_job(operations_response, done_event) # Execution will stop here and wait for the asynchronous steps in # _poll_batch_job to complete before proceeding. await done_event.wait() fetch_and_print_results(client, batch_job_service, resource_name) def create_batch_job_operation(client): """Created a BatchJobOperation and sets an empty BatchJob instance to the "create" property in order to tell the Google Ads API that we're creating a new BatchJob. Args: client: an initialized GoogleAdsClient instance. Returns: a BatchJobOperation with a BatchJob instance set in the "create" property. """ batch_job_operation = client.get_type("BatchJobOperation") batch_job = client.get_type("BatchJob") client.copy_from(batch_job_operation.create, batch_job) return batch_job_operation def create_batch_job(batch_job_service, customer_id, batch_job_operation): """Creates a batch job for the specified customer ID. Args: batch_job_service: an instance of the BatchJobService message class. customer_id: a str of a customer ID. batch_job_operation: a BatchJobOperation instance set to "create" Returns: a str of a resource name for a batch job. """ try: response = batch_job_service.mutate_batch_job( customer_id=customer_id, operation=batch_job_operation ) resource_name = response.result.resource_name print(f'Created a batch job with resource name "{resource_name}"') return resource_name except GoogleAdsException as exception: handle_googleads_exception(exception) def add_all_batch_job_operations(batch_job_service, operations, resource_name): """Adds all mutate operations to the batch job. As this is the first time for this batch job, we pass null as a sequence token. The response will contain the next sequence token that we can use to upload more operations in the future. Args: batch_job_service: an instance of the BatchJobService message class. operations: a list of a mutate operations. resource_name: a str of a resource name for a batch job. """ try: response = batch_job_service.add_batch_job_operations( resource_name=resource_name, sequence_token=None, mutate_operations=operations, ) print( f"{response.total_operations} mutate operations have been " "added so far." ) # You can use this next sequence token for calling # add_batch_job_operations() next time. print( "Next sequence token for adding next operations is " f"{response.next_sequence_token}" ) except GoogleAdsException as exception: handle_googleads_exception(exception) def build_all_operations(client, customer_id): """Builds all operations for creating a complete campaign. Args: client: an initialized GoogleAdsClient instance. customer_id: a str of a customer ID. Returns: a list of operations of various types. """ operations = [] # Creates a new campaign budget operation and adds it to the list of # mutate operations. campaign_budget_op = build_campaign_budget_operation(client, customer_id) operations.append( build_mutate_operation( client, "campaign_budget_operation", campaign_budget_op ) ) # Creates new campaign operations and adds them to the list of # mutate operations. campaign_operations = build_campaign_operations( client, customer_id, campaign_budget_op.create.resource_name ) operations = operations + [ build_mutate_operation(client, "campaign_operation", operation) for operation in campaign_operations ] # Creates new campaign criterion operations and adds them to the list of # mutate operations. campaign_criterion_operations = build_campaign_criterion_operations( client, campaign_operations ) operations = operations + [ build_mutate_operation( client, "campaign_criterion_operation", operation ) for operation in campaign_criterion_operations ] # Creates new ad group operations and adds them to the list of # mutate operations. ad_group_operations = build_ad_group_operations( client, customer_id, campaign_operations ) operations = operations + [ build_mutate_operation(client, "ad_group_operation", operation) for operation in ad_group_operations ] # Creates new ad group criterion operations and add them to the list of # mutate operations. ad_group_criterion_operations = build_ad_group_criterion_operations( client, ad_group_operations ) operations = operations + [ build_mutate_operation( client, "ad_group_criterion_operation", operation ) for operation in ad_group_criterion_operations ] # Creates new ad group ad operations and adds them to the list of # mutate operations. ad_group_ad_operations = build_ad_group_ad_operations( client, ad_group_operations ) operations = operations + [ build_mutate_operation(client, "ad_group_ad_operation", operation) for operation in ad_group_ad_operations ] return operations def build_campaign_budget_operation(client, customer_id): """Builds a new campaign budget operation for the given customer ID. Args: client: an initialized GoogleAdsClient instance. customer_id: a str of a customer ID. Returns: a CampaignBudgetOperation instance. """ campaign_budget_service = client.get_service("CampaignBudgetService") campaign_budget_operation = client.get_type("CampaignBudgetOperation") campaign_budget = campaign_budget_operation.create resource_name = campaign_budget_service.campaign_budget_path( customer_id, get_next_temporary_id() ) campaign_budget.resource_name = resource_name campaign_budget.name = f"Interplanetary Cruise Budget #{uuid4()}" campaign_budget.delivery_method = ( client.enums.BudgetDeliveryMethodEnum.STANDARD ) campaign_budget.amount_micros = 5000000 return campaign_budget_operation def build_campaign_operations( client, customer_id, campaign_budget_resource_name ): """Builds new campaign operations for the specified customer ID. Args: client: an initialized GoogleAdsClient instance. customer_id: a str of a customer ID. campaign_budget_resource_name: a str resource name for a campaign budget. Returns: a list of CampaignOperation instances. """ return [ build_campaign_operation( client, customer_id, campaign_budget_resource_name ) for i in range(NUMBER_OF_CAMPAIGNS_TO_ADD) ] def build_campaign_operation( client, customer_id, campaign_budget_resource_name ): """Builds new campaign operation for the specified customer ID. Args: client: an initialized GoogleAdsClient instance. customer_id: a str of a customer ID. campaign_budget_resource_name: a str resource name for a campaign budget. Returns: a CampaignOperation instance. """ campaign_operation = client.get_type("CampaignOperation") campaign_service = client.get_service("CampaignService") # Creates a campaign. campaign = campaign_operation.create campaign_id = get_next_temporary_id() # Creates a resource name using the temporary ID. campaign.resource_name = campaign_service.campaign_path( customer_id, campaign_id ) campaign.name = f"Batch job campaign #{customer_id}.{campaign_id}" campaign.advertising_channel_type = ( client.enums.AdvertisingChannelTypeEnum.SEARCH ) # Recommendation: Set the campaign to PAUSED when creating it to prevent # the ads from immediately serving. Set to ENABLED once you've added # targeting and the ads are ready to serve. campaign.status = client.enums.CampaignStatusEnum.PAUSED # Set the bidding strategy and type by setting manual_cpc equal to an empty # ManualCpc instance. client.copy_from(campaign.manual_cpc, client.get_type("ManualCpc")) campaign.campaign_budget = campaign_budget_resource_name return campaign_operation def build_campaign_criterion_operations(client, campaign_operations): """Builds new campaign criterion operations for negative keyword criteria. Args: client: an initialized GoogleAdsClient instance. campaign_operations: a list of CampaignOperation instances. Returns: a list of CampaignCriterionOperation instances. """ return [ build_campaign_criterion_operation(client, campaign_operation) for campaign_operation in campaign_operations ] def build_campaign_criterion_operation(client, campaign_operation): """Builds a new campaign criterion operation for negative keyword criterion. Args: client: an initialized GoogleAdsClient instance. campaign_operation: a CampaignOperation instance. Returns: a CampaignCriterionOperation instance. """ campaign_criterion_operation = client.get_type("CampaignCriterionOperation") # Creates a campaign criterion. campaign_criterion = campaign_criterion_operation.create campaign_criterion.keyword.text = "venus" campaign_criterion.keyword.match_type = ( client.enums.KeywordMatchTypeEnum.BROAD ) # Sets the campaign criterion as a negative criterion. campaign_criterion.negative = True campaign_criterion.campaign = campaign_operation.create.resource_name return campaign_criterion_operation def build_ad_group_operations(client, customer_id, campaign_operations): """Builds new ad group operations for the specified customer ID. Args: client: an initialized GoogleAdsClient instance. customer_id: a str of a customer ID. campaign_operations: a list of CampaignOperation instances. Return: a list of AdGroupOperation instances. """ operations = [] for campaign_operation in campaign_operations: for i in range(NUMBER_OF_AD_GROUPS_TO_ADD): operations.append( build_ad_group_operation( client, customer_id, campaign_operation ) ) return operations def build_ad_group_operation(client, customer_id, campaign_operation): """Builds a new ad group operation for the specified customer ID. Args: client: an initialized GoogleAdsClient instance. customer_id: a str of a customer ID. campaign_operation: a CampaignOperation instance. Return: an AdGroupOperation instance. """ ad_group_operation = client.get_type("AdGroupOperation") ad_group_service = client.get_service("AdGroupService") # Creates an ad group. ad_group = ad_group_operation.create ad_group_id = get_next_temporary_id() # Creates a resource name using the temporary ID. ad_group.resource_name = ad_group_service.ad_group_path( customer_id, ad_group_id ) ad_group.name = f"Batch job ad group #{uuid4()}.{ad_group_id}" ad_group.campaign = campaign_operation.create.resource_name ad_group.type_ = client.enums.AdGroupTypeEnum.SEARCH_STANDARD ad_group.cpc_bid_micros = 10000000 return ad_group_operation def build_ad_group_criterion_operations(client, ad_group_operations): """Builds new ad group criterion operations for creating keywords. 50% of keywords are created with some invalid characters to demonstrate how BatchJobService returns information about such errors. Args: client: an initialized GoogleAdsClient instance. ad_group_operations: a list of AdGroupOperation instances. Returns a list of AdGroupCriterionOperation instances. """ operations = [] for ad_group_operation in ad_group_operations: for i in range(NUMBER_OF_KEYWORDS_TO_ADD): operations.append( build_ad_group_criterion_operation( # Create a keyword text by making 50% of keywords invalid # to demonstrate error handling. client, ad_group_operation, i, i % 2 == 0, ) ) return operations def build_ad_group_criterion_operation( client, ad_group_operation, number, is_valid=True ): """Builds new ad group criterion operation for creating keywords. Takes an optional param that dictates whether the keyword text should intentionally generate an error with invalid characters. Args: client: an initialized GoogleAdsClient instance. ad_group_operation: an AdGroupOperation instance. number: an int of the number to assign to the name of the criterion. is_valid: a bool of whether the keyword text should be invalid. Returns: an AdGroupCriterionOperation instance. """ ad_group_criterion_operation = client.get_type("AdGroupCriterionOperation") # Creates an ad group criterion. ad_group_criterion = ad_group_criterion_operation.create ad_group_criterion.keyword.text = f"mars{number}" # If keyword should be invalid we add exclamation points, which will # generate errors when sent to the API. if not is_valid: ad_group_criterion.keyword.text += "!!!" ad_group_criterion.keyword.match_type = ( client.enums.KeywordMatchTypeEnum.BROAD ) ad_group_criterion.ad_group = ad_group_operation.create.resource_name ad_group_criterion.status = client.enums.AdGroupCriterionStatusEnum.ENABLED return ad_group_criterion_operation def build_ad_group_ad_operations(client, ad_group_operations): """Builds new ad group ad operations. Args: client: an initialized GoogleAdsClient instance. ad_group_operations: a list of AdGroupOperation instances. Returns: a list of AdGroupAdOperation instances. """ return [ build_ad_group_ad_operation(client, ad_group_operation) for ad_group_operation in ad_group_operations ] def build_ad_group_ad_operation(client, ad_group_operation): """Builds a new ad group ad operation. Args: client: an initialized GoogleAdsClient instance. ad_group_operation: an AdGroupOperation instance. Returns: an AdGroupAdOperation instance. """ ad_group_ad_operation = client.get_type("AdGroupAdOperation") # Creates an ad group ad. ad_group_ad = ad_group_ad_operation.create # Creates the expanded text ad info. text_ad = ad_group_ad.ad.expanded_text_ad text_ad.headline_part1 = f"Cruise to Mars #{uuid4()}" text_ad.headline_part2 = "Best Space Cruise Line" text_ad.description = "Buy your tickets now!" ad_group_ad.ad.final_urls.append("http://www.example.com") ad_group_ad.ad_group = ad_group_operation.create.resource_name ad_group_ad.status = client.enums.AdGroupAdStatusEnum.PAUSED return ad_group_ad_operation def run_batch_job(batch_job_service, resource_name): """Runs the batch job for executing all uploaded mutate operations. Args: batch_job_service: an instance of the BatchJobService message class. resource_name: a str of a resource name for a batch job. Returns: a google.api_core.operation.Operation instance. """ try: response = batch_job_service.run_batch_job(resource_name=resource_name) print( f'Batch job with resource name "{resource_name}" has been ' "executed." ) return response except GoogleAdsException as exception: handle_googleads_exception(exception) def poll_batch_job(operations_response, event): """Polls the server until the batch job execution finishes. Sets the initial poll delay time and the total time to wait before time-out. Args: operations_response: a google.api_core.operation.Operation instance. event: an instance of asyncio.Event to invoke once the operations have completed, alerting the awaiting calling code that it can proceed. """ loop = asyncio.get_event_loop() def done_callback(future): # The operations_response object will call callbacks from a daemon # thread so we must use a threadsafe method of setting the event here # otherwise it will not trigger the awaiting code. loop.call_soon_threadsafe(event.set) # operations_response represents a Long-Running Operation or LRO. The class # provides an interface for polling the API to check when the operation is # complete. Below we use the asynchronous interface, but there's also a # synchronous interface that uses the Operation.result method. # See: https://googleapis.dev/python/google-api-core/latest/operation.html operations_response.add_done_callback(done_callback) def fetch_and_print_results(client, batch_job_service, resource_name): """Prints all the results from running the batch job. Args: client: an initialized GoogleAdsClient instance. batch_job_service: an instance of the BatchJobService message class. resource_name: a str of a resource name for a batch job. """ print( f'Batch job with resource name "{resource_name}" has finished. ' "Now, printing its results..." ) list_results_request = client.get_type("ListBatchJobResultsRequest") list_results_request.resource_name = resource_name list_results_request.page_size = 1000 # Gets all the results from running batch job and prints their information. batch_job_results = batch_job_service.list_batch_job_results( request=list_results_request ) for batch_job_result in batch_job_results: status = batch_job_result.status.message status = status if status else "N/A" result = batch_job_result.mutate_operation_response result = result or "N/A" print( f"Batch job #{batch_job_result.operation_index} " f'has a status "{status}" and response type "{result}"' ) def handle_googleads_exception(exception): """Prints the details of a GoogleAdsException object. Args: exception: an instance of GoogleAdsException. """ print( f'Request with ID "{exception.request_id}" failed with status ' f'"{exception.error.code().name}" and includes the following errors:' ) for error in exception.failure.errors: print(f'\tError with message "{error.message}".') if error.location: for field_path_element in error.location.field_path_elements: print(f"\t\tOn field: {field_path_element.field_name}") sys.exit(1) if __name__ == "__main__": parser = argparse.ArgumentParser( description=( "Adds complete campaigns, including campaign budgets, " "campaigns, ad groups and keywords for the given " "customer ID using BatchJobService." ) ) # 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.", ) args = parser.parse_args() # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client = GoogleAdsClient.load_from_storage(version="v17") asyncio.run(main(googleads_client, args.customer_id))
Ruby
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright 2020 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 adds complete campaigns including campaign budgets, campaigns, # ad groups and keywords using BatchJobService. require 'optparse' require 'google/ads/google_ads' def add_complete_campaigns_using_batch_job(customer_id) # GoogleAdsClient will read a config file from # ENV['HOME']/google_ads_config.rb when called without parameters client = Google::Ads::GoogleAds::GoogleAdsClient.new batch_job_service = client.service.batch_job batch_job_resource_name = create_batch_job( client, batch_job_service, customer_id, ) add_all_batch_job_operations( client, batch_job_service, customer_id, batch_job_resource_name, ) operation_response = run_batch_job( batch_job_service, batch_job_resource_name, ) poll_batch_job(operation_response) fetch_and_print_results(batch_job_service, batch_job_resource_name) end # Creates a new batch job for the specified customer ID. def create_batch_job(client, batch_job_service, customer_id) # Creates a batch job operation to create a new batch job. operation = client.operation.create_resource.batch_job # Issues a request to the API and get the batch job's resource name. response = batch_job_service.mutate_batch_job( customer_id: customer_id, operation: operation ) batch_job_resource_name = response.result.resource_name puts "Created a batch job with resource name: '#{batch_job_resource_name}'" batch_job_resource_name end # Adds all batch job operations to the batch job. As this is the first time # for this batch job, pass null as a sequence token. The response will contain # the next sequence token that you can use to upload more operations in the # future. def add_all_batch_job_operations( client, batch_job_service, customer_id, batch_job_resource_name) response = batch_job_service.add_batch_job_operations( resource_name: batch_job_resource_name, mutate_operations: build_all_operations(client, customer_id), ) puts "#{response.total_operations} mutate operations have been added so far." # You can use this next sequence token for calling # add_all_batch_job_operations() next time puts "Next sequence token for adding next operations is " \ "'#{response.next_sequence_token}'" end # Requests the API to run the batch job for executing all uploaded batch job # operations. def run_batch_job(batch_job_service, batch_job_resource_name) operation_response = batch_job_service.run_batch_job( resource_name: batch_job_resource_name, ) puts "Batch job with resource name '#{batch_job_resource_name}' " \ "has been executed." operation_response end # Polls the server until the batch job execution finishes by setting the initial # poll delay time and the total time to wait before time-out. def poll_batch_job(operation_response) operation_response.wait_until_done! end # Prints all the results from running the batch job. def fetch_and_print_results(batch_job_service, batch_job_resource_name) puts "Batch job with resource name '#{batch_job_resource_name}' has " \ "finished. Now, printing its results..." \ # Gets all the results from running batch job and print their information. batch_job_results = batch_job_service.list_batch_job_results( resource_name: batch_job_resource_name, page_size: PAGE_SIZE, ) batch_job_results.each do |result| puts "Batch job ##{result.operation_index} has a status " \ "#{result.status ? result.status.message : 'N/A'} and response of type " \ "#{result.mutate_operation_response ? result.mutate_operation_response.response : 'N/A'}" end end # Builds all operations for creating a complete campaign and return an array of # their corresponding mutate operations. def build_all_operations(client, customer_id) mutate_operations = [] # Creates a new campaign budget operation and add it to the array of mutate # operations. campaign_budget_operation = build_campaign_budget_operation(client, customer_id) mutate_operations << client.operation.mutate do |mutate_op| mutate_op.campaign_budget_operation = campaign_budget_operation end # Creates new campaign operations and adds them to the array of mutate # operations. campaign_operations = build_campaign_operations( client, customer_id, campaign_budget_operation.create.resource_name) campaign_operations.each do |op| mutate_operations << client.operation.mutate do |mutate_op| mutate_op.campaign_operation = op end end # Creates new campaign criterion operations and adds them to the array of # mutate operations. campaign_criterion_operations = build_campaign_criterion_operations( client, campaign_operations) campaign_criterion_operations.each do |op| mutate_operations << client.operation.mutate do |mutate_op| mutate_op.campaign_criterion_operation = op end end # Creates new ad group operations and adds them to the array of mutate # operations. ad_group_operations = build_ad_group_operations( client, customer_id, campaign_operations) ad_group_operations.each do |op| mutate_operations << client.operation.mutate do |mutate_op| mutate_op.ad_group_operation = op end end # Creates new ad group criterion operations and adds them to the array of # mutate operations. ad_group_criterion_operations = build_ad_group_criterion_operations( client, ad_group_operations) ad_group_criterion_operations.each do |op| mutate_operations << client.operation.mutate do |mutate_op| mutate_op.ad_group_criterion_operation = op end end # Creates new ad group ad operations and adds them to the array of mutate # operations. ad_group_ad_operations = build_ad_group_ad_operations( client, ad_group_operations) ad_group_ad_operations.each do |op| mutate_operations << client.operation.mutate do |mutate_op| mutate_op.ad_group_ad_operation = op end end mutate_operations end # Builds a new campaign budget operation for the specified customer ID. def build_campaign_budget_operation(client, customer_id) # Creates a campaign budget operation. operation = client.operation.create_resource.campaign_budget do |b| # Creates a resource name using the temporary ID. b.resource_name = client.path.campaign_budget( customer_id, get_next_temporary_id) b.name = "Interplanetary Cruise Budget ##{(Time.new.to_f * 1000).to_i}" b.delivery_method = :STANDARD b.amount_micros = 5_000_000 end operation end # Builds new campaign operations for the specified customer ID. def build_campaign_operations(client, customer_id, campaign_budget_resource_name) operations = [] for i in 0..NUMBER_OF_CAMPAIGNS_TO_ADD-1 # Creates a campaign. campaign_id = get_next_temporary_id operations << client.operation.create_resource.campaign do |c| c.resource_name = client.path.campaign(customer_id, campaign_id) c.name = "Mutate job campaign ##{(Time.new.to_f * 1000).to_i}.#{campaign_id}" c.advertising_channel_type = :SEARCH # Recommendation: Set the campaign to PAUSED when creating it to prevent # the ads from immediately serving. Set to ENABLED once you've added # targeting and the ads are ready to serve. c.status = :PAUSED # Sets the bidding strategy and budget. c.manual_cpc = client.resource.manual_cpc c.campaign_budget = campaign_budget_resource_name end end operations end # Builds new campaign criterion operations for creating negative campaign # criteria (as keywords). def build_campaign_criterion_operations(client, campaign_operations) operations = [] campaign_operations.each do |op| operations << client.operation.create_resource.campaign_criterion do |cc| cc.keyword = client.resource.keyword_info do |k| k.text = "venus" k.match_type = :BROAD end cc.negative = true cc.campaign = op.create.resource_name end end operations end # Builds new ad group operations for the specified customer ID. def build_ad_group_operations(client, customer_id, campaign_operations) operations = [] campaign_operations.each do |op| for i in 0..NUMBER_OF_AD_GROUPS_TO_ADD-1 # Creates an ad group. ad_group_id = get_next_temporary_id operations << client.operation.create_resource.ad_group do |ag| # Creates a resource name using the temporary ID. ag.resource_name = client.path.ad_group(customer_id, ad_group_id) ag.name = "Mutate job ad group ##{(Time.new.to_f * 1000).to_i}.#{ad_group_id}" ag.campaign = op.create.resource_name ag.type = :SEARCH_STANDARD ag.cpc_bid_micros = 10_000_000 end end end operations end # Builds new ad group criterion operations for creating keywords. 50% of # keywords are created with some invalid characters to demonstrate how # BatchJobService returns information about such errors. def build_ad_group_criterion_operations(client, ad_group_operations) operations = [] ad_group_operations.each do |op| for i in 0..NUMBER_OF_KEYWORDS_TO_ADD-1 # Create a keyword text by making 50% of keywords invalid to demonstrate # error handling. keyword_text = "mars#{i}" if i % 2 == 0 keyword_text += "!!!" end # Creates an ad group criterion using the created keyword text. operations << client.operation.create_resource.ad_group_criterion do |agc| agc.keyword = client.resource.keyword_info do |k| k.text = keyword_text k.match_type = :BROAD end agc.ad_group = op.create.resource_name agc.status = :ENABLED end end end operations end # Builds new ad group ad operations. def build_ad_group_ad_operations(client, ad_group_operations) operations = [] ad_group_operations.each do |op| operations << client.operation.create_resource.ad_group_ad do |aga| aga.ad = client.resource.ad do |ad| ad.expanded_text_ad = client.resource.expanded_text_ad_info do |eta| eta.headline_part1 = "Cruise to Mars ##{(Time.new.to_f * 1000).to_i}" eta.headline_part2 = "Best Space Cruise Line" eta.description = "Buy your tickets now!" end ad.final_urls << "http://www.example.com" end aga.ad_group = op.create.resource_name aga.status = :PAUSED end end operations end # Returns the next temporary ID and decrease it by one. def get_next_temporary_id @temporary_id ||= 0 @temporary_id -= 1 end if __FILE__ == $0 NUMBER_OF_CAMPAIGNS_TO_ADD = 2; NUMBER_OF_AD_GROUPS_TO_ADD = 2; NUMBER_OF_KEYWORDS_TO_ADD = 4; PAGE_SIZE = 1000 options = {} 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.separator '' opts.separator 'Help:' opts.on_tail('-h', '--help', 'Show this message') do puts opts exit end end.parse! begin add_complete_campaigns_using_batch_job( options.fetch(:customer_id).tr("-", "")) 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("\tOn 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("\tType: %s\n\tCode: %s\n", k, v) end end raise end end
Perl
#!/usr/bin/perl -w # # Copyright 2019, 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 adds complete campaigns including campaign budgets, campaigns, # ad groups and keywords using BatchJobService. 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::V17::Resources::BatchJob; use Google::Ads::GoogleAds::V17::Resources::CampaignBudget; use Google::Ads::GoogleAds::V17::Resources::Campaign; use Google::Ads::GoogleAds::V17::Resources::CampaignCriterion; use Google::Ads::GoogleAds::V17::Resources::AdGroup; use Google::Ads::GoogleAds::V17::Resources::AdGroupCriterion; use Google::Ads::GoogleAds::V17::Resources::AdGroupAd; use Google::Ads::GoogleAds::V17::Resources::Ad; use Google::Ads::GoogleAds::V17::Common::ManualCpc; use Google::Ads::GoogleAds::V17::Common::KeywordInfo; use Google::Ads::GoogleAds::V17::Common::ExpandedTextAdInfo; use Google::Ads::GoogleAds::V17::Enums::BudgetDeliveryMethodEnum qw(STANDARD); use Google::Ads::GoogleAds::V17::Enums::AdvertisingChannelTypeEnum qw(SEARCH); use Google::Ads::GoogleAds::V17::Enums::CampaignStatusEnum; use Google::Ads::GoogleAds::V17::Enums::KeywordMatchTypeEnum qw(BROAD); use Google::Ads::GoogleAds::V17::Enums::AdGroupTypeEnum qw(SEARCH_STANDARD); use Google::Ads::GoogleAds::V17::Enums::AdGroupCriterionStatusEnum; use Google::Ads::GoogleAds::V17::Enums::AdGroupAdStatusEnum; use Google::Ads::GoogleAds::V17::Services::BatchJobService::BatchJobOperation; use Google::Ads::GoogleAds::V17::Services::GoogleAdsService::MutateOperation; use Google::Ads::GoogleAds::V17::Services::CampaignBudgetService::CampaignBudgetOperation; use Google::Ads::GoogleAds::V17::Services::CampaignService::CampaignOperation; use Google::Ads::GoogleAds::V17::Services::CampaignCriterionService::CampaignCriterionOperation; use Google::Ads::GoogleAds::V17::Services::AdGroupService::AdGroupOperation; use Google::Ads::GoogleAds::V17::Services::AdGroupCriterionService::AdGroupCriterionOperation; use Google::Ads::GoogleAds::V17::Services::AdGroupAdService::AdGroupAdOperation; use Google::Ads::GoogleAds::V17::Utils::ResourceNames; use Getopt::Long qw(:config auto_help); use Pod::Usage; use Cwd qw(abs_path); use Data::Uniqid qw(uniqid); use constant NUMBER_OF_CAMPAIGNS_TO_ADD => 2; use constant NUMBER_OF_AD_GROUPS_TO_ADD => 2; use constant NUMBER_OF_KEYWORDS_TO_ADD => 4; use constant POLL_FREQUENCY_SECONDS => 1; use constant POLL_TIMEOUT_SECONDS => 60; use constant PAGE_SIZE => 1000; # The following parameter(s) should be provided to run the example. You can # either specify these by changing the INSERT_XXX_ID_HERE values below, or on # the command line. # # Parameters passed on the command line will override any parameters set in # code. # # Running the example with -h will print the command line usage. my $customer_id = "INSERT_CUSTOMER_ID_HERE"; sub add_complete_campaigns_using_batch_job { my ($api_client, $customer_id) = @_; my $batch_job_service = $api_client->BatchJobService(); my $operation_service = $api_client->OperationService(); my $batch_job_resource_name = create_batch_job($batch_job_service, $customer_id); add_all_batch_job_operations($batch_job_service, $customer_id, $batch_job_resource_name); my $batch_job_lro = run_batch_job($batch_job_service, $batch_job_resource_name); poll_batch_job($operation_service, $batch_job_lro); fetch_and_print_results($batch_job_service, $batch_job_resource_name); return 1; } # Creates a new batch job for the specified customer ID. sub create_batch_job { my ($batch_job_service, $customer_id) = @_; # Create a batch job operation. my $batch_job_operation = Google::Ads::GoogleAds::V17::Services::BatchJobService::BatchJobOperation-> new({create => Google::Ads::GoogleAds::V17::Resources::BatchJob->new({})}); my $batch_job_resource_name = $batch_job_service->mutate({ customerId => $customer_id, operation => $batch_job_operation })->{result}{resourceName}; printf "Created a batch job with resource name: '%s'.\n", $batch_job_resource_name; return $batch_job_resource_name; } # Adds all batch job operations to the batch job. As this is the first time for # this batch job, pass null as a sequence token. The response will contain the # next sequence token that you can use to upload more operations in the future. sub add_all_batch_job_operations { my ($batch_job_service, $customer_id, $batch_job_resource_name) = @_; my $add_batch_job_operations_response = $batch_job_service->add_operations({ resourceName => $batch_job_resource_name, sequenceToken => undef, mutateOperations => build_all_operations($customer_id)}); printf "%d batch operations have been added so far.\n", $add_batch_job_operations_response->{totalOperations}; # You can use this next sequence token for calling add_operations() next time. printf "Next sequence token for adding next operations is '%s'.\n", $add_batch_job_operations_response->{nextSequenceToken}; } # Requests the API to run the batch job for executing all uploaded batch job # operations. sub run_batch_job { my ($batch_job_service, $batch_job_resource_name) = @_; my $batch_job_lro = $batch_job_service->run({resourceName => $batch_job_resource_name}); printf "Batch job with resource name '%s' has been executed.\n", $batch_job_resource_name; return $batch_job_lro; } # Polls the server until the batch job execution finishes by setting the initial # poll delay time and the total time to wait before time-out. sub poll_batch_job { my ($operation_service, $batch_job_lro) = @_; $operation_service->poll_until_done({ name => $batch_job_lro->{name}, pollFrequencySeconds => POLL_FREQUENCY_SECONDS, pollTimeoutSeconds => POLL_TIMEOUT_SECONDS }); } # Prints all the results from running the batch job. sub fetch_and_print_results { my ($batch_job_service, $batch_job_resource_name) = @_; printf "Batch job with resource name '%s' has finished. " . "Now, printing its results...\n", $batch_job_resource_name; # Get all the results from running batch job and print their information. my $list_batch_job_results_response = $batch_job_service->list_results({ resourceName => $batch_job_resource_name, pageSize => PAGE_SIZE }); foreach my $batch_job_result (@{$list_batch_job_results_response->{results}}) { printf "Batch job #%d has a status '%s' and response of type '%s'.\n", $batch_job_result->{operationIndex}, $batch_job_result->{status} ? $batch_job_result->{status}{message} : "N/A", $batch_job_result->{mutateOperationResponse} ? [keys %{$batch_job_result->{mutateOperationResponse}}]->[0] : "N/A"; } } # Builds all operations for creating a complete campaign and return an array of # their corresponding mutate operations. sub build_all_operations { my $customer_id = shift; my $mutate_operations = []; # Create a new campaign budget operation and add it to the array of mutate operations. my $campaign_budget_operation = build_campaign_budget_operation($customer_id); push @$mutate_operations, Google::Ads::GoogleAds::V17::Services::GoogleAdsService::MutateOperation-> new({ campaignBudgetOperation => $campaign_budget_operation }); # Create new campaign operations and add them to the array of mutate operations. my $campaign_operations = build_campaign_operations($customer_id, $campaign_budget_operation->{create}{resourceName}); push @$mutate_operations, map { Google::Ads::GoogleAds::V17::Services::GoogleAdsService::MutateOperation-> new({ campaignOperation => $_ }) } @$campaign_operations; # Create new campaign criterion operations and add them to the array of mutate # operations. my $campaign_criterion_operations = build_campaign_criterion_operations($campaign_operations); push @$mutate_operations, map { Google::Ads::GoogleAds::V17::Services::GoogleAdsService::MutateOperation-> new({ campaignCriterionOperation => $_ }) } @$campaign_criterion_operations; # Create new ad group operations and add them to the array of mutate operations. my $ad_group_operations = build_ad_group_operations($customer_id, $campaign_operations); push @$mutate_operations, map { Google::Ads::GoogleAds::V17::Services::GoogleAdsService::MutateOperation-> new({ adGroupOperation => $_ }) } @$ad_group_operations; # Create new ad group criterion operations and add them to the array of mutate # operations. my $ad_group_criterion_operations = build_ad_group_criterion_operations($ad_group_operations); push @$mutate_operations, map { Google::Ads::GoogleAds::V17::Services::GoogleAdsService::MutateOperation-> new({ adGroupCriterionOperation => $_ }) } @$ad_group_criterion_operations; # Create new ad group ad operations and add them to the array of mutate operations. my $ad_group_ad_operations = build_ad_group_ad_operations($ad_group_operations); push @$mutate_operations, map { Google::Ads::GoogleAds::V17::Services::GoogleAdsService::MutateOperation-> new({ adGroupAdOperation => $_ }) } @$ad_group_ad_operations; return $mutate_operations; } # Builds a new campaign budget operation for the specified customer ID. sub build_campaign_budget_operation { my $customer_id = shift; # Create a campaign budget operation. return Google::Ads::GoogleAds::V17::Services::CampaignBudgetService::CampaignBudgetOperation ->new({ create => Google::Ads::GoogleAds::V17::Resources::CampaignBudget->new({ # Create a resource name using the temporary ID. resourceName => Google::Ads::GoogleAds::V17::Utils::ResourceNames::campaign_budget( $customer_id, next_temporary_id() ), name => "Interplanetary Cruise Budget #" . uniqid(), deliveryMethod => STANDARD, amountMicros => 5000000 })}); } # Builds new campaign operations for the specified customer ID. sub build_campaign_operations { my ($customer_id, $campaign_budget_resource_name) = @_; my $campaign_operations = []; for (my $i = 0 ; $i < NUMBER_OF_CAMPAIGNS_TO_ADD ; $i++) { # Create a campaign. my $campaign_id = next_temporary_id(); my $campaign = Google::Ads::GoogleAds::V17::Resources::Campaign->new({ # Create a resource name using the temporary ID. resourceName => Google::Ads::GoogleAds::V17::Utils::ResourceNames::campaign( $customer_id, $campaign_id ), name => sprintf("Batch job campaign #%s.%d", uniqid(), $campaign_id), advertisingChannelType => SEARCH, # Recommendation: Set the campaign to PAUSED when creating it to prevent # the ads from immediately serving. Set to ENABLED once you've added # targeting and the ads are ready to serve. status => Google::Ads::GoogleAds::V17::Enums::CampaignStatusEnum::PAUSED, # Set the bidding strategy and budget. manualCpc => Google::Ads::GoogleAds::V17::Common::ManualCpc->new(), campaignBudget => $campaign_budget_resource_name, }); # Create a campaign operation and add it to the operations list. push @$campaign_operations, Google::Ads::GoogleAds::V17::Services::CampaignService::CampaignOperation ->new({ create => $campaign }); } return $campaign_operations; } # Builds new campaign criterion operations for creating negative campaign criteria # (as keywords). sub build_campaign_criterion_operations { my $campaign_operations = shift; my $campaign_criterion_operations = []; foreach my $campaign_operation (@$campaign_operations) { # Create a campaign criterion. my $campaign_criterion = Google::Ads::GoogleAds::V17::Resources::CampaignCriterion->new({ keyword => Google::Ads::GoogleAds::V17::Common::KeywordInfo->new({ text => "venus", matchType => BROAD } ), # Set the campaign criterion as a negative criterion. negative => "true", campaign => $campaign_operation->{create}{resourceName}}); # Create a campaign criterion operation and add it to the operations list. push @$campaign_criterion_operations, Google::Ads::GoogleAds::V17::Services::CampaignCriterionService::CampaignCriterionOperation ->new({ create => $campaign_criterion }); } return $campaign_criterion_operations; } # Builds new ad group operations for the specified customer ID. sub build_ad_group_operations { my ($customer_id, $campaign_operations) = @_; my $ad_group_operations = []; foreach my $campaign_operation (@$campaign_operations) { for (my $i = 0 ; $i < NUMBER_OF_AD_GROUPS_TO_ADD ; $i++) { # Create an ad group. my $ad_group_id = next_temporary_id(); my $ad_group = Google::Ads::GoogleAds::V17::Resources::AdGroup->new({ # Create a resource name using the temporary ID. resourceName => Google::Ads::GoogleAds::V17::Utils::ResourceNames::ad_group( $customer_id, $ad_group_id ), name => sprintf("Batch job ad group #%s.%d", uniqid(), $ad_group_id), campaign => $campaign_operation->{create}{resourceName}, type => SEARCH_STANDARD, cpcBidMicros => 10000000 }); # Create an ad group operation and add it to the operations list. push @$ad_group_operations, Google::Ads::GoogleAds::V17::Services::AdGroupService::AdGroupOperation ->new({ create => $ad_group }); } } return $ad_group_operations; } # Builds new ad group criterion operations for creating keywords. 50% of keywords # are created with some invalid characters to demonstrate how BatchJobService # returns information about such errors. sub build_ad_group_criterion_operations { my $ad_group_operations = shift; my $ad_group_criterion_operations = []; foreach my $ad_group_operation (@$ad_group_operations) { for (my $i = 0 ; $i < NUMBER_OF_KEYWORDS_TO_ADD ; $i++) { # Create a keyword text by making 50% of keywords invalid to demonstrate # error handling. my $keyword_text = "mars$i"; if ($i % 2 == 0) { $keyword_text = $keyword_text . '!!!'; } # Create an ad group criterion using the created keyword text. my $ad_group_criterion = Google::Ads::GoogleAds::V17::Resources::AdGroupCriterion->new({ keyword => Google::Ads::GoogleAds::V17::Common::KeywordInfo->new({ text => $keyword_text, matchType => BROAD } ), adGroup => $ad_group_operation->{create}{resourceName}, status => Google::Ads::GoogleAds::V17::Enums::AdGroupCriterionStatusEnum::ENABLED }); # Create an ad group criterion operation and add it to the operations list. push @$ad_group_criterion_operations, Google::Ads::GoogleAds::V17::Services::AdGroupCriterionService::AdGroupCriterionOperation ->new({ create => $ad_group_criterion }); } } return $ad_group_criterion_operations; } # Builds new ad group ad operations. sub build_ad_group_ad_operations { my $ad_group_operations = shift; my $ad_group_ad_operations = []; foreach my $ad_group_operation (@$ad_group_operations) { # Create an ad group ad. my $ad_group_ad = Google::Ads::GoogleAds::V17::Resources::AdGroupAd->new({ # Create the expanded text ad info. ad => Google::Ads::GoogleAds::V17::Resources::Ad->new({ # Set the expanded text ad info on an ad. expandedTextAd => Google::Ads::GoogleAds::V17::Common::ExpandedTextAdInfo->new({ headlinePart1 => "Cruise to Mars #" . uniqid(), headlinePart2 => "Best Space Cruise Line", description => "Buy your tickets now!" } ), finalUrls => "http://www.example.com", } ), adGroup => $ad_group_operation->{create}{resourceName}, status => Google::Ads::GoogleAds::V17::Enums::AdGroupAdStatusEnum::PAUSED }); # Create an ad group ad operation and add it to the operations list. push @$ad_group_ad_operations, Google::Ads::GoogleAds::V17::Services::AdGroupAdService::AdGroupAdOperation ->new({ create => $ad_group_ad }); } return $ad_group_ad_operations; } # Specifies a decreasing negative number for temporary IDs. # Returns -1, -2, -3, etc. on subsequent calls. sub next_temporary_id { our $temporary_id ||= 0; $temporary_id -= 1; } # Don't run the example if the file is being included. if (abs_path($0) ne abs_path(__FILE__)) { return 1; } # Get Google Ads Client, credentials will be read from ~/googleads.properties. my $api_client = Google::Ads::GoogleAds::Client->new(); # By default examples are set to die on any server returned fault. $api_client->set_die_on_faults(1); # Parameters passed on the command line will override any parameters set in code. GetOptions("customer_id=s" => \$customer_id); # 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_complete_campaigns_using_batch_job($api_client, $customer_id =~ s/-//gr); =pod =head1 NAME add_complete_campaigns_using_batch_job =head1 DESCRIPTION This example adds complete campaigns including campaign budgets, campaigns, ad groups and keywords using BatchJobService. =head1 SYNOPSIS add_complete_campaigns_using_batch_job.pl [options] -help Show the help message. -customer_id The Google Ads customer ID. =cut