Partial Failure

Some AdWords 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:

<partialFailure>true</partialFailure>

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:

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

List<AdGroupCriterionOperation> operations = new ArrayList<AdGroupCriterionOperation>();

// 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#

List<AdGroupCriterionOperation> operations = new List<AdGroupCriterionOperation>();

// 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();
  keyword.text = keywordText;
  keyword.matchType = KeywordMatchType.BROAD;

  // Create biddable ad group criterion.
  BiddableAdGroupCriterion keywordBiddableAdGroupCriterion = new BiddableAdGroupCriterion();
  keywordBiddableAdGroupCriterion.adGroupId = adGroupId;
  keywordBiddableAdGroupCriterion.criterion = keyword;

  // Create the operation.
  AdGroupCriterionOperation keywordAdGroupCriterionOperation =
      new AdGroupCriterionOperation();
  keywordAdGroupCriterionOperation.operand = keywordBiddableAdGroupCriterion;
  keywordAdGroupCriterionOperation.@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::v201708::Keyword->new({
      text      => "mars cruise",
      matchType => "BROAD"
    }
  ),
  Google::Ads::AdWords::v201708::Keyword->new({
      text      => "inv\@lid cruise",
      matchType => "BROAD"
    }
  ),
  Google::Ads::AdWords::v201708::Keyword->new({
      text      => "venus cruise",
      matchType => "BROAD"
    }
  ),
  Google::Ads::AdWords::v201708::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::v201708::BiddableAdGroupCriterion->new({
      adGroupId => $ad_group_id,
      criterion => $keyword
    });
  push @operations,
    Google::Ads::AdWords::v201708::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

for (AdGroupCriterion adGroupCriterionResult : result.getValue()) {
  if (adGroupCriterionResult.getCriterion() != null) {
    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::v201708::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 (available starting with v201702) or the fieldPath property (available in all versions) 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
      first_field_path_element['index']):
    operation_index = first_field_path_element['index']

    adgroup_criterion = operations[operation_index]['operand']

    print('Ad group criterion with ad group ID %d 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: %s\n'
           % 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:

Send feedback about...

AdWords API
AdWords API
Need help? Visit our support page.