Page Summary
-
Partial failures in Google Ads API operations can be detected by checking for empty results or error instances in the response.
-
The detailed error information for partial failures is available through a GoogleAdsFailure object, which needs to be deserialized to access error details.
-
This example demonstrates how to process a response with partial failures, identifying both successful and failed operations and displaying the corresponding error messages for the failures.
Java
// 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. package com.google.ads.googleads.examples.errorhandling ; 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.v22.errors.GoogleAdsError ; import com.google.ads.googleads.v22.errors.GoogleAdsException ; import com.google.ads.googleads.v22.errors.GoogleAdsFailure ; import com.google.ads.googleads.v22.resources.AdGroup ; import com.google.ads.googleads.v22.services.AdGroupOperation ; import com.google.ads.googleads.v22.services.AdGroupServiceClient ; import com.google.ads.googleads.v22.services.MutateAdGroupResult ; import com.google.ads.googleads.v22.services.MutateAdGroupsRequest ; import com.google.ads.googleads.v22.services.MutateAdGroupsResponse ; import com.google.ads.googleads.v22.utils.ErrorUtils ; import com.google.ads.googleads.v22.utils.ResourceNames ; import java.io.FileNotFoundException ; import java.io.IOException ; import java.util.Arrays ; /** * Shows how to handle partial failures. There are several ways of detecting partial failures. This * highlights the top main detection options: empty results and error instances. * * <p>Access to the detailed error (<code>GoogleAdsFailure</code>) for each error is via a Any * proto. Deserializing these to retrieve the error details is may not be immediately obvious at * first, this example shows how to convert Any into <code>GoogleAdsFailure</code>. * * <p>Additionally, this example shows how to produce an error message for a specific failed * operation by looking up the failure details in the <code>GoogleAdsFailure</code> object. */ public class HandlePartialFailure { private static class HandlePartialFailureParams extends CodeSampleParams { @Parameter ( names = ArgumentNames . CUSTOMER_ID , required = true ) private Long customerId ; @Parameter ( names = ArgumentNames . CAMPAIGN_ID , required = true ) private Long campaignId ; } public static void main ( String [] args ) { HandlePartialFailureParams params = new HandlePartialFailureParams (); 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" ); params . campaignId = Long . parseLong ( "INSERT_CAMPAIGN_ID" ); } 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 HandlePartialFailure (). runExample ( googleAdsClient , params . customerId , params . campaignId ); } catch ( GoogleAdsException gae ) { // GoogleAdsException is the base class for most exceptions thrown by an API request. // Instances of this exception have a message and a GoogleAdsFailure that contains a // collection of GoogleAdsErrors that indicate the underlying causes of the // GoogleAdsException. System . err . printf ( "Request ID %s failed due to GoogleAdsException. Underlying errors:%n" , gae . getRequestId ()); int i = 0 ; for ( GoogleAdsError googleAdsError : gae . getGoogleAdsFailure (). getErrorsList ()) { System . err . printf ( " Error %d: %s%n" , i ++ , googleAdsError ); } System . exit ( 1 ); } } /** Runs the example. */ public void runExample ( GoogleAdsClient googleAdsClient , long customerId , long campaignId ) { MutateAdGroupsResponse response = createAdGroups ( googleAdsClient , customerId , campaignId ); // Checks for existence of any partial failures in the response. if ( checkIfPartialFailureErrorExists ( response )) { System . out . println ( "Partial failures occurred." ); } else { System . out . println ( "All operations completed successfully. No partial failures to show." ); return ; } // Finds the failed operations by looping through the results. printResults ( response ); } /** * Attempts to create 3 ad groups with partial failure enabled. One of the ad groups will succeed, * while the other will fail. */ private MutateAdGroupsResponse createAdGroups ( GoogleAdsClient googleAdsClient , long customerId , long campaignId ) { // This AdGroup should be created successfully - assuming the campaign in the params exists. AdGroup group1 = AdGroup . newBuilder () . setCampaign ( ResourceNames . campaign ( customerId , campaignId )) . setName ( "Valid AdGroup: " + getPrintableDateTime ()) . build (); // This AdGroup will always fail - campaign ID 0 in resource names is never valid. AdGroup group2 = AdGroup . newBuilder () . setCampaign ( ResourceNames . campaign ( customerId , 0 L )) . setName ( "Broken AdGroup: " + getPrintableDateTime ()) . build (); // This AdGroup will always fail - duplicate ad group names are not allowed. AdGroup group3 = AdGroup . newBuilder () . setCampaign ( ResourceNames . campaign ( customerId , campaignId )) . setName ( group1 . getName ()) . build (); AdGroupOperation op1 = AdGroupOperation . newBuilder (). setCreate ( group1 ). build (); AdGroupOperation op2 = AdGroupOperation . newBuilder (). setCreate ( group2 ). build (); AdGroupOperation op3 = AdGroupOperation . newBuilder (). setCreate ( group3 ). build (); try ( AdGroupServiceClient service = googleAdsClient . getLatestVersion (). createAdGroupServiceClient ()) { // Issues the mutate request, setting partialFailure=true. return service . mutateAdGroups ( MutateAdGroupsRequest . newBuilder () . setCustomerId ( String . valueOf ( customerId )) . setCustomerId ( Long . toString ( customerId )) . addAllOperations ( Arrays . asList ( op1 , op2 , op3 )) . setPartialFailure ( true ) . build ()); } } /** Inspects a response to check for presence of partial failure errors. */ private boolean checkIfPartialFailureErrorExists ( MutateAdGroupsResponse response ) { return response . hasPartialFailureError (); } /** Displays the result from the mutate operation. */ private void printResults ( MutateAdGroupsResponse response ) { int operationIndex = 0 ; for ( MutateAdGroupResult result : response . getResultsList ()) { if ( ErrorUtils . getInstance (). isPartialFailureResult ( result )) { // May throw on this line. Most likely this means the wrong version of the ErrorUtils // class has been used. GoogleAdsFailure googleAdsFailure = ErrorUtils . getInstance () . getGoogleAdsFailure ( response . getPartialFailureError ()); for ( GoogleAdsError error : ErrorUtils . getInstance () . getGoogleAdsErrors ( operationIndex , googleAdsFailure )) { System . out . printf ( "Operation %d failed with error: %s%n" , operationIndex , error ); } } else { System . out . printf ( "Operation %d succeeded.%n" , operationIndex ); } ++ operationIndex ; } } }
C#
// 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. using CommandLine ; using Google.Ads.Gax.Examples ; using Google.Ads.Gax.Lib ; using Google.Ads.GoogleAds.Lib ; using Google.Ads.GoogleAds.V22.Errors ; using Google.Ads.GoogleAds.V22.Resources ; using Google.Ads.GoogleAds.V22.Services ; using System ; using System.Collections.Generic ; namespace Google.Ads.GoogleAds.Examples.V22 { /// <summary> /// This code example demonstrates how to handle partial failures. /// </summary> public class HandlePartialFailure : ExampleBase { /// <summary> /// Command line options for running the <see cref="HandlePartialFailure"/> example. /// </summary> public class Options : OptionsBase { /// <summary> /// The customer ID for which the call is made. /// </summary> [Option("customerId", Required = true, HelpText = "The customer ID for which the call is made.")] public long CustomerId { get ; set ; } /// <summary> /// ID of the campaign to which ad groups are added. /// </summary> [Option("campaignId", Required = true, HelpText = "ID of the campaign to which ad groups are added.")] public long CampaignId { 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 ); HandlePartialFailure codeExample = new HandlePartialFailure (); Console . WriteLine ( codeExample . Description ); codeExample . Run ( new GoogleAdsClient (), options . CustomerId , options . CampaignId ); } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description = > "This code example demonstrates how to handle partial failures." ; /// <summary> /// Runs the code example. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The customer ID for which the call is made.</param> /// <param name="campaignId">ID of the campaign to which ad groups are added.</param> public void Run ( GoogleAdsClient client , long customerId , long campaignId ) { try { MutateAdGroupsResponse response = CreateAdGroups ( client , customerId , campaignId ); // Checks for existence of any partial failures in the response. if ( CheckIfPartialFailureErrorExists ( response )) { Console . WriteLine ( "Partial failures occurred. Details will be shown below." ); } else { Console . WriteLine ( "All operations completed successfully. No partial " + "failures to show." ); return ; } // Finds the failed operations by looping through the results. PrintResults ( response ); } catch ( GoogleAdsException e ) { Console . WriteLine ( "Failure:" ); Console . WriteLine ( $"Message: {e.Message}" ); Console . WriteLine ( $"Failure: {e.Failure}" ); Console . WriteLine ( $"Request ID: {e.RequestId}" ); throw ; } } /// <summary> /// Displays the result from the mutate operation. /// </summary> /// <param name="response">The mutate response from the Google Ads API server..</param> private void PrintResults ( MutateAdGroupsResponse response ) { // Finds the failed operations by looping through the results. int operationIndex = 0 ; foreach ( MutateAdGroupResult result in response . Results ) { // This represents the result of a failed operation. if ( result . IsEmpty ()) { List<GoogleAdsError> errors = response . PartialFailure . GetErrorsByOperationIndex ( operationIndex ); foreach ( GoogleAdsError error in errors ) { Console . WriteLine ( $"Operation {operationIndex} failed with " + $"error: {error}." ); } } else { Console . WriteLine ( $"Operation {operationIndex} succeeded." , operationIndex ); } operationIndex ++ ; } } /// <summary> /// Inspects a response to check for presence of partial failure errors. /// </summary> /// <param name="response">The response.</param> /// <returns>True if there are partial failures, false otherwise.</returns> private static bool CheckIfPartialFailureErrorExists ( MutateAdGroupsResponse response ) { return response . PartialFailureError != null ; } /// <summary> /// Attempts to create 3 ad groups with partial failure enabled. One of the ad groups /// will succeed, while the other will fail. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The customer ID for which the call is made.</param> /// <param name="campaignId">ID of the campaign to which ad groups are added.</param> /// <returns>The mutate response from the Google Ads server.</returns> private static MutateAdGroupsResponse CreateAdGroups ( GoogleAdsClient client , long customerId , long campaignId ) { // Get the AdGroupServiceClient. AdGroupServiceClient adGroupService = client . GetService ( Services . V22 . AdGroupService ); string validAdGroupName = "Valid AdGroup: " + ExampleUtilities . GetRandomString (); AdGroupOperation [] operations = new AdGroupOperation [] { // This operation will be successful, assuming the campaign specified in // campaignId parameter is correct. new AdGroupOperation () { Create = new AdGroup () { Campaign = ResourceNames . Campaign ( customerId , campaignId ), Name = validAdGroupName } }, // This operation will fail since we are using campaign ID = 0, which results // in an invalid resource name. new AdGroupOperation () { Create = new AdGroup () { Campaign = ResourceNames . Campaign ( customerId , 0 ), Name = "Broken AdGroup: " + ExampleUtilities . GetRandomString () }, }, // This operation will fail since the ad group is using the same name as the ad // group from the first operation. Duplicate ad group names are not allowed. new AdGroupOperation () { Create = new AdGroup () { Campaign = ResourceNames . Campaign ( customerId , campaignId ), Name = validAdGroupName } } }; // Add the ad groups. MutateAdGroupsResponse response = adGroupService . MutateAdGroups ( new MutateAdGroupsRequest () { CustomerId = customerId . ToString (), Operations = { operations }, PartialFailure = true , ValidateOnly = false }); return response ; } } }
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\ErrorHandling; 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\V22\GoogleAdsClient; use Google\Ads\GoogleAds\Lib\V22\GoogleAdsClientBuilder; use Google\Ads\GoogleAds\Lib\V22\GoogleAdsException; use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder; use Google\Ads\GoogleAds\Util\V22\GoogleAdsErrors; use Google\Ads\GoogleAds\Util\V22\PartialFailures; use Google\Ads\GoogleAds\Util\V22\ResourceNames; use Google\Ads\GoogleAds\V22\Errors\GoogleAdsError; use Google\Ads\GoogleAds\V22\Resources\AdGroup; use Google\Ads\GoogleAds\V22\Services\AdGroupOperation; use Google\Ads\GoogleAds\V22\Services\MutateAdGroupsRequest; use Google\Ads\GoogleAds\V22\Services\MutateAdGroupsResponse; use Google\ApiCore\ApiException; /** * Shows how to handle partial failures. There are several ways of detecting partial failures. This * highlights the top main detection options: empty results and error instances. * * <p>Access to the detailed error (<code>GoogleAdsFailure</code>) for each error is via a Any * proto. Deserializing these to retrieve the error details is may not be immediately obvious at * first, this example shows how to convert Any into <code>GoogleAdsFailure</code>. * * <p>Additionally, this example shows how to produce an error message for a specific failed * operation by looking up the failure details in the <code>GoogleAdsFailure</code> object. */ class HandlePartialFailure { private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE'; private const CAMPAIGN_ID = 'INSERT_CAMPAIGN_ID_HERE'; public static function main() { // Either pass the required parameters for this example on the command line, or insert them // into the constants above. $options = (new ArgumentParser())->parseCommandArguments([ ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT, ArgumentNames::CAMPAIGN_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, $options[ArgumentNames::CAMPAIGN_ID] ?: self::CAMPAIGN_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 * @param int $campaignId a campaign ID */ public static function runExample( GoogleAdsClient $googleAdsClient, int $customerId, int $campaignId ) { $response = self::createAdGroups($googleAdsClient, $customerId, $campaignId); self::checkIfPartialFailureErrorExists($response); self::printResults($response); } /** * Create ad groups by enabling partial failure mode. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param int $campaignId a campaign ID * @return MutateAdGroupsResponse */ private static function createAdGroups( GoogleAdsClient $googleAdsClient, int $customerId, int $campaignId ) { $campaignResourceName = ResourceNames::forCampaign($customerId, $campaignId); // This ad group should be created successfully - assuming the campaign in the params // exists. $adGroup1 = new AdGroup([ 'name' => 'Valid AdGroup #' . Helper::getPrintableDatetime(), 'campaign' => $campaignResourceName ]); // This ad group will always fail - campaign ID 0 in the resource name is never valid. $adGroup2 = new AdGroup([ 'name' => 'Broken AdGroup #' . Helper::getPrintableDatetime(), 'campaign' => ResourceNames::forCampaign($customerId, 0) ]); // This ad group will always fail - duplicate ad group names are not allowed. $adGroup3 = new AdGroup([ 'name' => $adGroup1->getName(), 'campaign' => $campaignResourceName ]); $operations = []; $adGroupOperation1 = new AdGroupOperation(); $adGroupOperation1->setCreate($adGroup1); $operations[] = $adGroupOperation1; $adGroupOperation2 = new AdGroupOperation(); $adGroupOperation2->setCreate($adGroup2); $operations[] = $adGroupOperation2; $adGroupOperation3 = new AdGroupOperation(); $adGroupOperation3->setCreate($adGroup3); $operations[] = $adGroupOperation3; // Issues the mutate request, enabling partial failure mode. $adGroupServiceClient = $googleAdsClient->getAdGroupServiceClient(); return $adGroupServiceClient->mutateAdGroups( MutateAdGroupsRequest::build($customerId, $operations)->setPartialFailure(true) ); } /** * Check if there exists partial failure error in the given mutate ad group response. * * @param MutateAdGroupsResponse $response the mutate ad group response */ private static function checkIfPartialFailureErrorExists(MutateAdGroupsResponse $response) { if ($response->hasPartialFailureError()) { printf("Partial failures occurred. Details will be shown below.%s", PHP_EOL); } else { printf( "All operations completed successfully. No partial failures to show.%s", PHP_EOL ); } } /** * Print results of the given mutate ad group response. For those that are partial failure, * print all their errors with corresponding operation indices. For those that succeeded, print * the resource names of created ad groups. * * @param MutateAdGroupsResponse $response the mutate ad group response */ private static function printResults(MutateAdGroupsResponse $response) { // Finds the failed operations by looping through the results. $operationIndex = 0; foreach ($response->getResults() as $result) { /** @var AdGroup $result */ if (PartialFailures::isPartialFailure($result)) { $errors = GoogleAdsErrors::fromStatus( $operationIndex, $response->getPartialFailureError() ); foreach ($errors as $error) { printf( "Operation %d failed with error: %s%s", $operationIndex, $error->getMessage(), PHP_EOL ); } } else { printf( "Operation %d succeeded: ad group with resource name '%s'.%s", $operationIndex, $result->getResourceName(), PHP_EOL ); } $operationIndex++; } } } HandlePartialFailure::main();
Python
#!/usr/bin/env python # Copyright 2018 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 shows how to handle responses that may include partial_failure errors.""" import argparse import sys import uuid from typing import Any , List from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException from google.ads.googleads.v22.services.services.ad_group_service import ( AdGroupServiceClient , ) from google.ads.googleads.v22.services.services.campaign_service import ( CampaignServiceClient , ) from google.ads.googleads.v22.services.types.ad_group_service import ( AdGroupOperation , MutateAdGroupsResponse , MutateAdGroupsRequest , ) def main ( client : GoogleAdsClient , customer_id : str , campaign_id : str ) - > None : """Runs the example code, which demonstrates how to handle partial failures. The example creates three Ad Groups, two of which intentionally fail in order to generate a partial failure error. It also demonstrates how to properly identify a partial error and how to log the error messages. Args: client: An initialized GoogleAdsClient instance. customer_id: A valid customer account ID. campaign_id: The ID for a campaign to create Ad Groups under. """ try : ad_group_response : MutateAdGroupsResponse = create_ad_groups ( client , customer_id , campaign_id ) except GoogleAdsException as ex : print ( f 'Request with ID " { ex . request_id } " failed with status ' f '" { ex . error . code () . name } " and includes the following errors:' ) for error in ex . failure . errors : print ( f ' \t Error with message " { error . message } ".' ) if error . location : for field_path_element in error . location . field_path_elements : print ( f " \t\t On field: { field_path_element . field_name } " ) sys . exit ( 1 ) else : print_results ( client , ad_group_response ) def create_ad_groups ( client : GoogleAdsClient , customer_id : str , campaign_id : str ) - > MutateAdGroupsResponse : """Creates three Ad Groups, two of which intentionally generate errors. Args: client: An initialized GoogleAdsClient instance. customer_id: A valid customer account ID. campaign_id: The ID for a campaign to create Ad Groups under. Returns: A MutateAdGroupsResponse message instance. """ ad_group_service : AdGroupServiceClient = client . get_service ( "AdGroupService" ) campaign_service : CampaignServiceClient = client . get_service ( "CampaignService" ) resource_name : str = campaign_service . campaign_path ( customer_id , campaign_id ) invalid_resource_name : str = campaign_service . campaign_path ( customer_id , 0 ) ad_group_operations : List [ AdGroupOperation ] = [] # This AdGroup should be created successfully - assuming the campaign in # the params exists. ad_group_op1 : AdGroupOperation = client . get_type ( "AdGroupOperation" ) ad_group_op1 . create . name = f "Valid AdGroup: { uuid . uuid4 () } " ad_group_op1 . create . campaign = resource_name ad_group_operations . append ( ad_group_op1 ) # This AdGroup will always fail - campaign ID 0 in resource names is # never valid. ad_group_op2 : AdGroupOperation = client . get_type ( "AdGroupOperation" ) ad_group_op2 . create . name = f "Broken AdGroup: { uuid . uuid4 () } " ad_group_op2 . create . campaign = invalid_resource_name ad_group_operations . append ( ad_group_op2 ) # This AdGroup will always fail - duplicate ad group names are not allowed. ad_group_op3 : AdGroupOperation = client . get_type ( "AdGroupOperation" ) ad_group_op3 . create . name = ad_group_op1 . create . name ad_group_op3 . create . campaign = resource_name ad_group_operations . append ( ad_group_op3 ) # Issue a mutate request, setting partial_failure=True. request : MutateAdGroupsRequest = client . get_type ( "MutateAdGroupsRequest" ) request . customer_id = customer_id request . operations = ad_group_operations request . partial_failure = True return ad_group_service . mutate_ad_groups ( request = request ) def is_partial_failure_error_present ( response : MutateAdGroupsResponse ) - > bool : """Checks whether a response message has a partial failure error. In Python the partial_failure_error attr is always present on a response message and is represented by a google.rpc.Status message. So we can't simply check whether the field is present, we must check that the code is non-zero. Error codes are represented by the google.rpc.Code proto Enum: https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto Args: response: A MutateAdGroupsResponse message instance. Returns: A boolean, whether or not the response message has a partial failure error. """ partial_failure : Any = getattr ( response , "partial_failure_error" , None ) code : int = int ( getattr ( partial_failure , "code" , 0 )) # Default to 0 if None return code != 0 def print_results ( client : GoogleAdsClient , response : MutateAdGroupsResponse ) - > None : """Prints partial failure errors and success messages from a response. This function shows how to retrieve partial_failure errors from a response message (in the case of this example the message will be of type MutateAdGroupsResponse) and how to unpack those errors to GoogleAdsFailure instances. It also shows that a response with partial failures may still contain successful requests, and that those messages should be parsed separately. As an example, a GoogleAdsFailure object from this example will be structured similar to: error_code { range_error: TOO_LOW } message: "Too low." trigger { string_value: "" } location { field_path_elements { field_name: "operations" index { value: 1 } } field_path_elements { field_name: "create" } field_path_elements { field_name: "campaign" } } Args: client: an initialized GoogleAdsClient. response: a MutateAdGroupsResponse instance. """ # Check for existence of any partial failures in the response. if is_partial_failure_error_present ( response ): print ( "Partial failures occurred. Details will be shown below. \n " ) # Prints the details of the partial failure errors. partial_failure : Any = getattr ( response , "partial_failure_error" , None ) # partial_failure_error.details is a repeated field and iterable error_details : List [ Any ] = getattr ( partial_failure , "details" , []) for error_detail in error_details : # Retrieve an instance of the GoogleAdsFailure class from the client failure_message : Any = client . get_type ( "GoogleAdsFailure" ) # Parse the string into a GoogleAdsFailure message instance. # To access class-only methods on the message we retrieve its type. GoogleAdsFailure : Any = type ( failure_message ) failure_object : Any = GoogleAdsFailure . deserialize ( error_detail . value ) for error in failure_object . errors : # Construct and print a string that details which element in # the above ad_group_operations list failed (by index number) # as well as the error message and error code. print ( "A partial failure at index " f " { error . location . field_path_elements [ 0 ] . index } occurred " f " \n Error message: { error . message } \n Error code: " f " { error . error_code } " ) else : print ( "All operations completed successfully. No partial failure " "to show." ) # In the list of results, operations from the ad_group_operation list # that failed will be represented as empty messages. This loop detects # such empty messages and ignores them, while printing information about # successful operations. for message in response . results : if not message : continue print ( f "Created ad group with resource_name: { message . resource_name } ." ) if __name__ == "__main__" : parser = argparse . ArgumentParser ( description = "Adds an ad group for specified customer and campaign id." ) # The following argument(s) should be provided to run the example. parser . add_argument ( "-c" , "--customer_id" , type = str , required = True , help = "The Google Ads customer ID." , ) parser . add_argument ( "-i" , "--campaign_id" , type = str , required = True , help = "The campaign 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 = GoogleAdsClient . load_from_storage ( version = "v22" ) main ( googleads_client , args . customer_id , args . campaign_id )
Ruby
# Encoding: utf-8 # # 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. # # This code example shows how to deal with partial failures require 'optparse' require 'google/ads/google_ads' require 'date' def add_ad_groups ( customer_id , campaign_id ) # GoogleAdsClient will read a config file from # ENV['HOME']/google_ads_config.rb when called without parameters client = Google :: Ads :: GoogleAds :: GoogleAdsClient . new ad_groups = [] # This ad group should be created successfully. ad_groups << client . resource . ad_group do | ag | ag . campaign = client . path . campaign ( customer_id , campaign_id ) ag . name = "Valid ad group: #{ ( Time . new . to_f * 1000 ) . to_i } " end # This ad group should fail to create because it references an invalid campaign. ad_groups << client . resource . ad_group do | ag | ag . campaign = client . path . campaign ( customer_id , 0 ) ag . name = "Invalid ad group: #{ ( Time . new . to_f * 1000 ) . to_i } " end # This ad group should fail to create because it duplicates the name from the first one. ad_groups << client . resource . ad_group do | ag | ag . campaign = client . path . campaign ( customer_id , campaign_id ) ag . name = ad_groups . first . name end operations = ad_groups . map do | ag | client . operation . create_resource . ad_group ( ag ) end response = client . service . ad_group . mutate_ad_groups ( customer_id : customer_id , operations : operations , partial_failure : true , ) response . results . each_with_index do | ad_group , i | if ad_group . resource_name != "" puts ( "operations[ #{ i } ] succeeded: Created ad group with id #{ ad_group . resource_name } " ) end end failures = client . decode_partial_failure_error ( response . partial_failure_error ) failures . each do | failure | failure . errors . each do | error | human_readable_error_path = error . location . field_path_elements . map { | location_info | if location_info . index " #{ location_info . field_name } [ #{ location_info . index } ]" else " #{ location_info . field_name } " end } . join ( " > " ) errmsg = "error occured creating ad group #{ human_readable_error_path } " \ " with value: #{ error . trigger . string_value } " \ " because #{ error . message . downcase } " puts errmsg end end end if __FILE__ == $PROGRAM_NAME options = {} # The following parameter(s) should be provided to run the example. You can # either specify these by changing the INSERT_XXX_ID_HERE values below, or on # the command line. # # Parameters passed on the command line will override any parameters set in # code. # # Running the example with -h will print the command line usage. options [ :customer_id ] = 'INSERT_CUSTOMER_ID_HERE' options [ :campaign_id ] = 'INSERT_CAMPAIGN_ID_HERE' OptionParser . new do | opts | opts . banner = sprintf ( 'Usage: ruby %s [options]' , File . basename ( __FILE__ )) opts . separator '' opts . separator 'Options:' opts . on ( '-C' , '--customer-id CUSTOMER-ID' , String , 'Customer ID' ) do | v | options [ :customer_id ] = v end opts . on ( '-c' , '--campaign-id CAMPAIGN-ID' , String , 'Ad Group ID' ) do | v | options [ :campaign_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_ad_groups ( options . fetch ( :customer_id ) . tr ( "-" , "" ), options . fetch ( :campaign_id ), ) rescue Google :: Ads :: GoogleAds :: Errors :: GoogleAdsError = > e e . failure . errors . each do | error | STDERR . printf ( "Error with message: %s \n " , error . message ) if error . location error . location . field_path_elements . each do | field_path_element | STDERR . printf ( " \t On field: %s \n " , field_path_element . field_name ) end end error . error_code . to_h . each do | k , v | next if v == :UNSPECIFIED STDERR . printf ( " \t Type: %s \n\t Code: %s \n " , k , v ) end end raise end end
Perl
#!/usr/bin/perl -w # # Copyright 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 shows how to deal with partial failures. There are several ways # of detecting partial failures. This example highlights the top main detection # options: empty results and error instances. use strict ; use warnings ; use utf8 ; use FindBin qw($Bin) ; use lib "$Bin/../../lib" ; use Google::Ads::GoogleAds::Client ; use Google::Ads::GoogleAds::Utils::GoogleAdsHelper ; use Google::Ads::GoogleAds::Utils::PartialFailureUtils ; use Google::Ads::GoogleAds::V22::Resources::AdGroup ; use Google::Ads::GoogleAds::V22::Services::AdGroupService::AdGroupOperation ; use Google::Ads::GoogleAds::V22::Utils::ResourceNames ; use Getopt::Long qw(:config auto_help) ; use Pod::Usage ; use Cwd qw(abs_path) ; use Data::Uniqid qw(uniqid) ; # 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" ; my $campaign_id = "INSERT_CAMPAIGN_ID_HERE" ; sub handle_partial_failure { my ( $api_client , $customer_id , $campaign_id ) = @_ ; my $ad_groups_response = create_ad_groups ( $api_client , $customer_id , $campaign_id ); check_if_partial_failure_error_exists ( $ad_groups_response ); print_results ( $ad_groups_response ); return 1 ; } # Creates ad groups by enabling partial failure mode. sub create_ad_groups { my ( $api_client , $customer_id , $campaign_id ) = @_ ; my $campaign_resource_name = Google::Ads::GoogleAds::V22::Utils::ResourceNames:: campaign ( $customer_id , $campaign_id ); # This ad group should be created successfully - assuming the campaign in the # params exists. my $ad_group1 = Google::Ads::GoogleAds::V22::Resources:: AdGroup - > new ({ name = > "Valid AdGroup: " . uniqid (), campaign = > $campaign_resource_name }); # This ad group will always fail - campaign ID 0 in the resource name is never # valid. my $ad_group2 = Google::Ads::GoogleAds::V22::Resources:: AdGroup - > new ({ name = > "Broken AdGroup: " . uniqid (), campaign = > Google::Ads::GoogleAds::V22::Utils::ResourceNames:: campaign ( $customer_id , 0 )}); # This ad group will always fail - duplicate ad group names are not allowed. my $ad_group3 = Google::Ads::GoogleAds::V22::Resources:: AdGroup - > new ({ name = > $ad_group1 - > { name }, campaign = > $campaign_resource_name }); # Create ad group operations. my $ad_group_operation1 = Google::Ads::GoogleAds::V22::Services::AdGroupService:: AdGroupOperation - > new ({ create = > $ad_group1 }); my $ad_group_operation2 = Google::Ads::GoogleAds::V22::Services::AdGroupService:: AdGroupOperation - > new ({ create = > $ad_group2 }); my $ad_group_operation3 = Google::Ads::GoogleAds::V22::Services::AdGroupService:: AdGroupOperation - > new ({ create = > $ad_group3 }); # Issue the mutate request, enabling partial failure mode. my $ad_groups_response = $api_client - > AdGroupService () - > mutate ({ customerId = > $customer_id , operations = > [ $ad_group_operation1 , $ad_group_operation2 , $ad_group_operation3 ], partialFailure = > "true" }); return $ad_groups_response ; } # Checks if partial failure error exists in the given mutate ad group response. sub check_if_partial_failure_error_exists { my $ad_groups_response = shift ; if ( $ad_groups_response - > { partialFailureError }) { print "Partial failures occurred. Details will be shown below.\n" ; } else { print "All operations completed successfully. No partial failures to show.\n" ; } } # Prints results of the given mutate ad group response. For those that are partial # failure, prints all their errors with corresponding operation indices. For those # that succeeded, prints the resource names of created ad groups. sub print_results { my $ad_groups_response = shift ; # Find the failed operations by looping through the results. while ( my ( $operation_index , $result ) = each @ { $ad_groups_response - > { results }}) { if ( is_partial_failure_result ( $result )) { my $google_ads_errors = get_google_ads_errors ( $operation_index , $ad_groups_response - > { partialFailureError }); foreach my $google_ads_error ( @$google_ads_errors ) { printf "Operation %d failed with error: %s\n" , $operation_index , $google_ads_error - > { message }; } } else { printf "Operation %d succeeded: ad group with resource name '%s'.\n" , $operation_index , $result - > { resourceName }; } } } # Don't run the example if the file is being included. if ( abs_path ( $0 ) ne abs_path ( __FILE__ )) { return 1 ; } # Get Google Ads Client, credentials will be read from ~/googleads.properties. my $api_client = Google::Ads::GoogleAds:: Client - > new (); # By default examples are set to die on any server returned fault. $api_client - > set_die_on_faults ( 1 ); # Parameters passed on the command line will override any parameters set in code. GetOptions ( "customer_id=s" = > \ $customer_id , "campaign_id=i" = > \ $campaign_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 , $campaign_id ); # Call the example. handle_partial_failure ( $api_client , $customer_id =~ s/-//g r , $campaign_id ); =pod =head1 NAME handle_partial_failure =head1 DESCRIPTION This example shows how to deal with partial failures. There are several ways of detecting partial failures. This example highlights the top main detection options: empty results and error instances. =head1 SYNOPSIS handle_partial_failure.pl [options] -help Show the help message. -customer_id The Google Ads customer ID. -campaign_id The campaign ID. =cut

