Some AdWords API services allow you to request that valid operations be committed
and failed ones return errors. This feature, called partial failure, allows you
to handle the failed operations separately at the end.
Technical details
To utilize this feature, you’ll need to set this optional SOAP header:
true
The service will carry out the operations that had no errors. It will return
results for successful operations and errors for failed ones. This header is
ignored for non-mutate operations.
This feature is supported by the following services:
- AdGroupAdService
- AdGroupBidModifierService
- AdGroupCriterionService
- AdGroupExtensionSettingService
- AdGroupService
- BudgetService
- CampaignCriterionService
- CampaignExtensionSettingService
- CampaignService
- CustomerExtensionSettingService
- FeedItemService
- OfflineConversionFeedService
- SharedSetService
Usage
Assume that you need to add a set of keywords to your account. However, some of
the keywords may have editorial policy violations. You want to submit the valid
keywords, but have the failed keywords returned along with their errors.
Create the service
Start by enabling partialFailure
mode as follows:
Java
// Enable partial failure. session.setPartialFailure(true);
C#
// Set partial failure mode for the service. adGroupCriterionService.RequestHeader.partialFailure = true;
Python
client.partial_failure = True
PHP
// Construct an API session configured from a properties file and the // OAuth2 credentials above. // Partial failure behavior is also enabled in this example. $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->enablePartialFailure() ->build();
Perl
# Setting partial failures flag. $client->set_partial_failure(1);
Ruby
# Set partial failures flag. adwords.partial_failure = true
VB.NET
' Set partial failure mode for the service. adGroupCriterionService.RequestHeader.partialFailure = True
Create the operations and make the API call
Create the mutate operations and make the API call as usual.
Java
Listoperations = new ArrayList<>(); // Create keywords. String[] keywords = new String[] {"mars cruise", "inv@lid cruise", "venus cruise", "b(a)d keyword cruise"}; for (String keywordText : keywords) { // Create keyword Keyword keyword = new Keyword(); keyword.setText(keywordText); keyword.setMatchType(KeywordMatchType.BROAD); // Create biddable ad group criterion. BiddableAdGroupCriterion keywordBiddableAdGroupCriterion = new BiddableAdGroupCriterion(); keywordBiddableAdGroupCriterion.setAdGroupId(adGroupId); keywordBiddableAdGroupCriterion.setCriterion(keyword); // Create operation. AdGroupCriterionOperation keywordAdGroupCriterionOperation = new AdGroupCriterionOperation(); keywordAdGroupCriterionOperation.setOperand(keywordBiddableAdGroupCriterion); keywordAdGroupCriterionOperation.setOperator(Operator.ADD); operations.add(keywordAdGroupCriterionOperation); } // Add ad group criteria. AdGroupCriterionReturnValue result = adGroupCriterionService.mutate(operations.toArray(new AdGroupCriterionOperation[] {}));
C#
Listoperations = new List (); // Create the keywords. string[] keywords = new string[] { "mars cruise", "inv@lid cruise", "venus cruise", "b(a)d keyword cruise" }; foreach (string keywordText in keywords) { Keyword keyword = new Keyword { text = keywordText, matchType = KeywordMatchType.BROAD }; // Create biddable ad group criterion. BiddableAdGroupCriterion keywordBiddableAdGroupCriterion = new BiddableAdGroupCriterion { adGroupId = adGroupId, criterion = keyword }; // Create the operation. AdGroupCriterionOperation keywordAdGroupCriterionOperation = new AdGroupCriterionOperation { operand = keywordBiddableAdGroupCriterion, @operator = Operator.ADD }; operations.Add(keywordAdGroupCriterionOperation); } // Create the keywords. AdGroupCriterionReturnValue result = adGroupCriterionService.mutate(operations.ToArray());
Python
# Construct keyword ad group criteria objects. keywords = [ { 'xsi_type': 'BiddableAdGroupCriterion', 'adGroupId': ad_group_id, 'criterion': { 'xsi_type': 'Keyword', 'matchType': 'BROAD', 'text': 'mars cruise' } }, { 'xsi_type': 'BiddableAdGroupCriterion', 'adGroupId': ad_group_id, 'criterion': { 'xsi_type': 'Keyword', 'matchType': 'BROAD', 'text': r'inv@lid cruise' } }, { 'xsi_type': 'BiddableAdGroupCriterion', 'adGroupId': ad_group_id, 'criterion': { 'xsi_type': 'Keyword', 'matchType': 'BROAD', 'text': 'venus cruise' } }, { 'xsi_type': 'BiddableAdGroupCriterion', 'adGroupId': ad_group_id, 'criterion': { 'xsi_type': 'Keyword', 'matchType': 'BROAD', 'text': r'b(a)d keyword cruise' } } ] # Construct operations and add ad group criteria. operations = [] for keyword in keywords: operations.append( { 'operator': 'ADD', 'operand': keyword }) result = ad_group_criterion_service.mutate(operations)
PHP
$keywords = []; $keyword = new Keyword(); $keyword->setText('mars cruise'); $keyword->setMatchType(KeywordMatchType::BROAD); $keywords[] = $keyword; $keyword = new Keyword(); $keyword->setText('inv@lid cruise'); $keyword->setMatchType(KeywordMatchType::BROAD); $keywords[] = $keyword; $keyword = new Keyword(); $keyword->setText('venus cruise'); $keyword->setMatchType(KeywordMatchType::BROAD); $keywords[] = $keyword; $keyword = new Keyword(); $keyword->setText('b(a)d keyword cruise'); $keyword->setMatchType(KeywordMatchType::BROAD); $keywords[] = $keyword; // Create ad group criteria and ad group criterion operations. $operations = []; foreach ($keywords as $keyword) { $adGroupCriterion = new BiddableAdGroupCriterion(); $adGroupCriterion->setAdGroupId($adGroupId); $adGroupCriterion->setCriterion($keyword); $operation = new AdGroupCriterionOperation(); $operation->setOperand($adGroupCriterion); $operation->setOperator(Operator::ADD); $operations[] = $operation; } // Create ad group criteria on the server. $result = $adGroupCriterionService->mutate($operations);
Perl
# Create keywords. my @keywords = ( Google::Ads::AdWords::v201809::Keyword->new({ text => "mars cruise", matchType => "BROAD" } ), Google::Ads::AdWords::v201809::Keyword->new({ text => "inv@lid cruise", matchType => "BROAD" } ), Google::Ads::AdWords::v201809::Keyword->new({ text => "venus cruise", matchType => "BROAD" } ), Google::Ads::AdWords::v201809::Keyword->new({ text => "b(a)d keyword cruise", matchType => "BROAD" })); # Create biddable ad group criterions and operations. my @operations = (); for my $keyword (@keywords) { my $keyword_biddable_ad_group_criterion = Google::Ads::AdWords::v201809::BiddableAdGroupCriterion->new({ adGroupId => $ad_group_id, criterion => $keyword }); push @operations, Google::Ads::AdWords::v201809::AdGroupCriterionOperation->new({ operator => "ADD", operand => $keyword_biddable_ad_group_criterion }); } # Add ad group criteria. my $result = $client->AdGroupCriterionService()->mutate({operations => @operations});
Ruby
# Create keywords. keyword_text = ['mars cruise', 'inv@lid cruise', 'venus cruise', 'b(a)d keyword cruise'] keywords = [] keyword_text.each do |text| keyword = { # The 'xsi_type' field allows you to specify the xsi:type of the object # being created. It's only necessary when you must provide an explicit # type that the client library can't infer. :xsi_type => 'Keyword', :match_type => 'BROAD', :text => text } keywords << keyword end # Create biddable ad group criteria and operations. operations = [] keywords.each do |kwd| operation = { :operator => 'ADD', :operand => { :xsi_type => 'BiddableAdGroupCriterion', :ad_group_id => ad_group_id, :criterion => kwd } } operations << operation end # Add ad group criteria. response = ad_group_criterion_srv.mutate(operations)
VB.NET
Dim operations As New List(Of AdGroupCriterionOperation) ' Create the keywords. Dim keywords As String() = New String() { _ "mars cruise", "inv@lid cruise", "venus cruise", "b(a)d keyword cruise"} For Each keywordText As String In keywords Dim keyword As New Keyword keyword.text = keywordText keyword.matchType = KeywordMatchType.BROAD ' Create biddable ad group criterion. Dim keywordBiddableAdGroupCriterion As New BiddableAdGroupCriterion keywordBiddableAdGroupCriterion.adGroupId = adGroupId keywordBiddableAdGroupCriterion.criterion = keyword ' Create the operation. Dim keywordAdGroupCriterionOperation As New AdGroupCriterionOperation keywordAdGroupCriterionOperation.operand = keywordBiddableAdGroupCriterion keywordAdGroupCriterionOperation.operator = [Operator].ADD operations.Add(keywordAdGroupCriterionOperation) Next ' Create the keywords. Dim result As AdGroupCriterionReturnValue = adGroupCriterionService.mutate( operations.ToArray)
Handle the successful operations
Successful operations return result values by the service. Print them out if
desired:
Java
Arrays.stream(result.getValue()) .filter(adGroupCriterionResult -> adGroupCriterionResult.getCriterion() != null) .forEach( adGroupCriterionResult -> System.out.printf( "Ad group criterion with ad group ID %d, and criterion ID %d, " + "and keyword '%s' was added.%n", adGroupCriterionResult.getAdGroupId(), adGroupCriterionResult.getCriterion().getId(), ((Keyword) adGroupCriterionResult.getCriterion()).getText()));
C#
// Display the results. if (result != null && result.value != null) { foreach (AdGroupCriterion adGroupCriterionResult in result.value) { if (adGroupCriterionResult.criterion != null) { Console.WriteLine( "Keyword with ad group id '{0}', criterion id '{1}', and " + "text '{2}' was added.n", adGroupCriterionResult.adGroupId, adGroupCriterionResult.criterion.id, ((Keyword) adGroupCriterionResult.criterion).text); } } } else { Console.WriteLine("No keywords were added."); }
Python
for criterion in result['value']: if criterion['AdGroupCriterion.Type'] == 'BiddableAdGroupCriterion': print('Added keyword ad group criterion with ad group id "%s", ' 'criterion id "%s", text "%s", and match type "%s" was ' 'added.' % (criterion['adGroupId'], criterion['criterion']['id'], criterion['criterion']['text'], criterion['criterion']['matchType']))
PHP
foreach ($result->getValue() as $adGroupCriterion) { if ($adGroupCriterion->getCriterion() !== null) { printf( "Keyword with text '%s', match type '%s', and ID %d was added.n", $adGroupCriterion->getCriterion()->getText(), $adGroupCriterion->getCriterion()->getMatchType(), $adGroupCriterion->getCriterion()->getId() ); } }
Perl
if ($result->get_value() || $result->get_partialFailureErrors()) { # Display added criteria. foreach my $ad_group_criterion (@{$result->get_value()}) { if ( $ad_group_criterion->isa( "Google::Ads::AdWords::v201809::BiddableAdGroupCriterion")) { printf "Ad group criterion with ad group id "%d", criterion id " . ""%d", and keyword "%s" was added.n", $ad_group_criterion->get_adGroupId(), $ad_group_criterion->get_criterion()->get_id(), $ad_group_criterion->get_criterion()->get_text(); } }
Ruby
if response and response[:value] ad_group_criteria = response[:value] ad_group_criteria.each do |ad_group_criterion| if ad_group_criterion[:criterion] puts ("Ad group criterion with ad group id %d, criterion id %d, and " + " keyword '%s' was added.") % [ ad_group_criterion[:ad_group_id], ad_group_criterion[:criterion][:id], ad_group_criterion[:criterion][:text] ] end end else puts "No criteria were added." end
VB.NET
' Display the results. If ((Not result Is Nothing) AndAlso (Not result.value Is Nothing)) Then For Each adGroupCriterionResult As AdGroupCriterion In result.value If (Not adGroupCriterionResult.criterion Is Nothing) Then Console.WriteLine( "Keyword with ad group id '{0}', and criterion id " & "'{1}', and text '{2}' was added.n", adGroupCriterionResult.adGroupId, adGroupCriterionResult.criterion.id, DirectCast(adGroupCriterionResult.criterion, Keyword).text) End If Next Else Console.WriteLine("No keywords were added.") End If
Handle the failed operations
Failed operations return error information in the partialFailureErrors
field.
You can find the index of the failed operation by looking at the
fieldPathElements
property or the
fieldPath
property of the
ApiError
object in the partialFailures
list.
Java
for (ApiError apiError : result.getPartialFailureErrors()) { // Get the index of the failed operation from the error's field path elements. FieldPathElement[] fieldPathElements = apiError.getFieldPathElements(); FieldPathElement firstFieldPathElement = null; if (fieldPathElements != null && fieldPathElements.length > 0) { firstFieldPathElement = fieldPathElements[0]; } if (firstFieldPathElement != null && "operations".equals(firstFieldPathElement.getField()) && firstFieldPathElement.getIndex() != null) { int operationIndex = firstFieldPathElement.getIndex(); AdGroupCriterion adGroupCriterion = operations.get(operationIndex).getOperand(); System.out.printf( "Ad group criterion with ad group ID %d and keyword '%s' " + "triggered a failure for the following reason: %s.%n", adGroupCriterion.getAdGroupId(), ((Keyword) adGroupCriterion.getCriterion()).getText(), apiError.getErrorString()); } else { System.out.printf( "A failure has occurred for the following reason: %s%n", apiError.getErrorString()); } }
C#
// Display the partial failure errors. if (result != null && result.partialFailureErrors != null) { foreach (ApiError apiError in result.partialFailureErrors) { int operationIndex = apiError.GetOperationIndex(); if (operationIndex != -1) { AdGroupCriterion adGroupCriterion = operations[operationIndex].operand; Console.WriteLine( "Keyword with ad group id '{0}' and text '{1}' " + "triggered a failure for the following reason: '{2}'.n", adGroupCriterion.adGroupId, ((Keyword) adGroupCriterion.criterion).text, apiError.errorString); } else { Console.WriteLine( "A failure for the following reason: '{0}' has occurred.n", apiError.errorString); } } }
Python
for error in result['partialFailureErrors']: field_path_elements = error['fieldPathElements'] first_field_path_element = None if field_path_elements: first_field_path_element = field_path_elements[0] if (first_field_path_element and first_field_path_element['field'] == 'operations' and 'index' in first_field_path_element): operation_index = first_field_path_element['index'] adgroup_criterion = operations[operation_index]['operand'] print('Ad group criterion with ad group ID %s and keyword "%s" triggered ' 'a failure for the following reason: %s.' % (adgroup_criterion['adGroupId'], adgroup_criterion['criterion']['text'], error['errorString'])) else: print('A failure has occurred for the following reasons: %sn' % error['errorString'])
PHP
if ($result->getPartialFailureErrors() !== null) { foreach ($result->getPartialFailureErrors() as $error) { // Get the index of the failed operation from the error's field path // elements. $fieldPathElements = $error->getFieldPathElements(); $firstFieldPathElement = null; if ($fieldPathElements !== null && count($fieldPathElements) > 0) { $firstFieldPathElement = $fieldPathElements[0]; } if ($firstFieldPathElement !== null && $firstFieldPathElement->getField() === 'operations' && $firstFieldPathElement->getIndex() !== null) { $index = $firstFieldPathElement->getIndex(); $adGroupCriterion = $operations[$index]->getOperand(); printf( "Keyword with text '%s' and match type '%s' failed with error '%s'.n", $adGroupCriterion->getCriterion()->getText(), $adGroupCriterion->getCriterion()->getMatchType(), $error->getErrorString() ); } else { printf( "Operations failed with error '%s'.n", $error->getErrorString() ); } } }
Perl
foreach my $error (@{$result->get_partialFailureErrors()}) { # Get the index of the failed operation from the error's field path # elements. my $field_path_elements = $error->get_fieldPathElements(); my $first_field_path_element = ($field_path_elements && (scalar $field_path_elements > 0)) ? $field_path_elements->[0] : undef; if ( $first_field_path_element && $first_field_path_element->get_field() eq "operations" && defined $first_field_path_element->get_index()) { my $error_index = $first_field_path_element->get_index(); my $ad_group_criterion = $operations[$error_index]->get_operand(); printf "Ad group criterion with ad group id "%d" and keyword " . ""%s" as trigger a failure for the following reason: " . ""%s".n", $ad_group_criterion->get_adGroupId(), $ad_group_criterion->get_criterion()->get_text(), $error->get_errorString(); } else { printf "A failure for the following reason: "%s" has ocurred.n", $error->get_errorString(); } }
Ruby
# Check partial failures. if response and response[:partial_failure_errors] response[:partial_failure_errors].each do |error| field_path_elements = error[:field_path_elements] first_field_path_element = nil unless field_path_elements.nil? || field_path_elements.length <= 0 first_field_path_element = field_path_elements.first end if !first_field_path_element.nil? && 'operations' == first_field_path_element[:field] && first_field_path_element[:index] != nil operation_index = first_field_path_element[:index] ad_group_criterion = operations[operation_index][:operand] puts ("Ad group criterion with ad group id %d and keyword '%s' " + "triggered an error for the following reason: %s") % [ ad_group_criterion[:ad_group_id], ad_group_criterion[:criterion][:text], error[:error_string] ] else puts "A failure has occurred for the following reason: '%s'" % error[:error_string] end end end
VB.NET
' Display the partial failure errors. If _ ((Not result Is Nothing) AndAlso (Not result.partialFailureErrors Is Nothing)) Then For Each apiError As ApiError In result.partialFailureErrors Dim operationIndex As Integer = apiError.GetOperationIndex() If (operationIndex <> - 1) Then Dim adGroupCriterion As AdGroupCriterion = operations(operationIndex).operand Console.WriteLine("Keyword with ad group id '{0}' and text '{1}' " & "triggered a failure for the following reason: " & "'{2}'.n", adGroupCriterion.adGroupId, DirectCast(adGroupCriterion.criterion, Keyword). text, apiError.errorString) Else Console.WriteLine( "A failure for the following reason: '{0}' has occurred.n", apiError.errorString) End If Next End If
Code examples
The ErrorHandling
folder of each client library
contains the following code example that shows how to use this feature: