Solicitações de isenção de política

As solicitações de isenção permitem o envio automático de solicitações de análise de palavras-chave e anúncios que acionam violações de política.

É possível usar este recurso, por exemplo, quando:

  • o anúncio contém sinais de pontuação que normalmente são considerados pouco convencionais, mas que seguem os padrões do setor;
  • a palavra-chave no seu grupo de anúncios contém termos médicos, mas você (ou os usuários) acredita que o uso do termo obedece às políticas do Google AdWords e requer uma análise mais criteriosa.

Nessas situações, sua primeira tentativa de criar o anúncio ou a palavra-chave falhará com um PolicyViolationError.

Se você preencheu o conjunto exemptionRequests dos seus anúncios e das palavras-chave, eles serão automaticamente enviados para análise. Dependendo do resultado da análise, talvez você seja capaz de reenviar seus anúncios ou palavras-chave com êxito usando a operação ADD.

Importante: não basta reenviar todos os anúncios ou palavras-chave que geram um PolicyViolationError depois de adicionar as solicitações de isenção. Tente reenviar somente os anúncios ou palavras-chave que, na sua visão, obedecem às nossas políticas de publicidade e requerem uma análise mais criteriosa. Se seus anúncios ou palavras-chave forem reprovados repetidamente por violar nossas políticas de publicidade, sua conta do Google AdWords poderá ser suspensa.

Caso um anúncio seja enviado com sucesso sem um PolicyViolationError, mas depois seja reprovado devido a uma violação da política de anúncios, você encontrará mais detalhes no AdGroupAdPolicySummary.

As seções abaixo explicam as etapas necessárias para o envio de solicitações de isenção.

Procurar erros de violação da política em cada operação com falha

Digamos que você esteja criando três anúncios em uma única chamada para AdGroupAdService.mutate():

  • Os anúncios A e B contêm o mesmo termo médico no título.
  • O anúncio B também contém sinais de pontuação não convencionais no título.
  • O anúncio C contém um texto que não está na forma padrão ou que não é fiel ao conteúdo do site de destino.

Quando você envia uma chamada de serviço que contém três exemplares de AdGroupAdOperations, a solicitação falha retornando os seguintes erros:

Erro PolicyViolationError.fieldPath PolicyViolationError.isExemptable PolicyViolationKey.policyName
PolicyViolationError 0 (anúncio A) verdadeiro pharma
PolicyViolationError 1 (anúncio B) verdadeiro pharma
PolicyViolationError 1 (anúncio B) verdadeiro nonstandard_punctuation
PolicyViolationError 2 (anúncio C) falso unclear_or_inaccurate_ad_text

Manter as operações com violações de políticas passíveis de isenção

Como os erros das operações 0 e 1 são passíveis de isenção, é possível reenviá-los com solicitações de isenção. No entanto, o erro da operação 2 não é passível de isenção, portanto, não há motivo para reenviar a operação.

O snippet de código a seguir repete os erros na resposta e mantém o index de cada operação que falhou com um erro de violação de política isento.

Java

for (ApiError error : e.getErrors()) {
  // Get the index of the failed operation from the error's field path elements.
  FieldPathElement[] fieldPathElements = error.getFieldPathElements();
  FieldPathElement firstFieldPathElement = null;
  if (fieldPathElements != null && fieldPathElements.length > 0) {
    firstFieldPathElement = fieldPathElements[0];
  }
  if (firstFieldPathElement == null
      || !"operations".equals(firstFieldPathElement.getField())
      || firstFieldPathElement.getIndex() == null) {
    // If the operation index is not present on the first error field path element, then
    // there's no way to determine which operation to remove, so simply throw the exception.
    throw e;
  }
  int operationIndex = firstFieldPathElement.getIndex();
  AdGroupAdOperation operation = operations[operationIndex];
  if (handleApiError(error, operationIndex, operation)) {
    operationIndicesToRetry.add(operationIndex);
  } else {
    System.out.printf(
        "Removing operation with non-exemptable error at index %d.%n", operationIndex);
  }
}

CSharp

ApiException innerException = e.ApiException as ApiException;
if (innerException == null) {
  throw new Exception("Failed to retrieve ApiError. See inner exception for more " +
      "details.", e);
}

// Examine each ApiError received from the server.
foreach (ApiError apiError in innerException.errors) {
  int index = apiError.GetOperationIndex();
  if (index == -1) {
    // This API error is not associated with an operand, so we cannot
    // recover from this error by removing one or more operations.
    // Rethrow the exception for manual inspection.
    throw;
  }

  // Handle policy violation errors.
  if (apiError is PolicyViolationError) {
    PolicyViolationError policyError = (PolicyViolationError) apiError;

    if (policyError.isExemptable) {
      // If the policy violation error is exemptable, add an exemption
      // request.
      List<ExemptionRequest> exemptionRequests = new List<ExemptionRequest>();
      if (allOperations[index].exemptionRequests != null) {
        exemptionRequests.AddRange(allOperations[index].exemptionRequests);
      }

      ExemptionRequest exemptionRequest = new ExemptionRequest();
      exemptionRequest.key = policyError.key;
      exemptionRequests.Add(exemptionRequest);
      allOperations[index].exemptionRequests = exemptionRequests.ToArray();
    } else {
      // Policy violation error is not exemptable, remove this
      // operation from the list of operations.
      operationsToBeRemoved.Add(allOperations[index]);
    }
  } else {
    // This is not a policy violation error, remove this operation
    // from the list of operations.
    operationsToBeRemoved.Add(allOperations[index]);
  }
}

Python

for error in e.errors:
  # Get the index of the failed operation from the error's field path
  # elements.
  field_path_elements = error['fieldPathElements']
  first_field_path_element = None

  if field_path_elements:
    first_field_path_element = field_path_elements[0]

  # If the operation index is not present on the first error field path
  # element, then there's no way to determine which operation to remove,
  # so simply throw the exception.
  if (not (first_field_path_element
           and first_field_path_element['field'] == 'operations'
           and 'index' in first_field_path_element)):
    raise e

  index = long(first_field_path_element['index'])
  operation = operations[index]
  if not HandleAPIError(error, operation):
    # Set non-exemptable operation to None to mark for deletion.
    print ('Removing operation with non-exemptable error at index %s.'
           % index)
    operations[index] = None

PHP

foreach ($apiException->getErrors() 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) {
        // If the operation index is not present on the first error field
        // path element, then there's no way to determine which operation to
        // remove, so simply throw the exception.
        throw $apiException;
    }
    $operationIndex = $firstFieldPathElement->getIndex();
    $operation = $operations[$operationIndex];
    if (self::handleApiError($error, $operationIndex, $operation)) {
        // Store the index of operations we want to retry as indices of the
        // bucket.
        $operationIndicesToRetryBucket[$operationIndex] = 1;
    } else {
        printf(
            "Removing operation with non-exemptable error at index %d.\n",
            $operationIndex
        );
    }
}

Perl

foreach
  my $error (@{$result->get_detail()->get_ApiExceptionFault()->get_errors()})
{
  # 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 $operation_index = $first_field_path_element->get_index();
    my $operation       = $operations[$operation_index];
    if ($error->get_ApiError__Type() =~ "PolicyViolationError") {
      printf "Ad with headline '%s' violated '%s' policy '%s'.\n",
        $operation->get_operand()->get_ad()->get_headlinePart1(),
        $error->get_isExemptable ? 'exemptable' : 'non-exemptable',
        $error->get_externalPolicyName();

      if ($error->get_isExemptable()) {
        # Add exemption request to the operation.
        printf(
          "Adding exemption request for policy name '%s' on text " .
            "'%s'.\n",
          $error->get_key()->get_policyName(),
          $error->get_key()->get_violatingText());
        $operation->set_exemptionRequests([
            new Google::Ads::AdWords::v201802::ExemptionRequest(
              {key => $error->get_key()})]);
      } else {
        # Remove non-exemptable operation.
        print "Removing from the request.\n";
        push @operation_indicies_to_remove, $operation_index;
      }
    } else {
      # Non-policy error returned, remove ad.
      print "Removing from the request.\n";
      push @operation_indicies_to_remove, $operation_index;
    }
  }
}

Ruby

e.errors.each do |error|
  if error[:xsi_type] == 'PolicyViolationError'
    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?
      # If the operation index is not present on the first error field path
      # element, then there's no way to determine which operation to
      # remove, so simply throw the exception.
      raise e
    end

    operation_index = first_field_path_element[:index]
    operation = operations[operation_index]
    process_api_error(error, operation)
    unless error[:is_exemptable]
      # Remove non-exemptable operation
      puts "Removing the operation from the request."
      operations.delete(operation)
    end
  else
    # Non-policy error returned, re-throw exception.
    raise e
  end
end

VB.NET

Dim innerException As ApiException = TryCast(e.ApiException, ApiException)
If (innerException Is Nothing) Then
  Throw New Exception("Failed to retrieve ApiError. See inner exception for more " &
      "details.", e)
End If

' Examine each ApiError received from the server.
For Each apiError As ApiError In innerException.errors
  Dim index As Integer = apiError.GetOperationIndex()
  If (index = -1) Then
    ' This API error is not associated with an operand, so we cannot
    ' recover from this error by removing one or more operations.
    ' Rethrow the exception for manual inspection.
    Throw
  End If

  ' Handle policy violation errors.
  If TypeOf apiError Is PolicyViolationError Then
    Dim policyError As PolicyViolationError = CType(apiError, PolicyViolationError)

    If policyError.isExemptable Then
      ' If the policy violation error is exemptable, add an exemption
      ' request.
      Dim exemptionRequests As New List(Of ExemptionRequest)
      If (Not allOperations.Item(index).exemptionRequests Is Nothing) Then
        exemptionRequests.AddRange(allOperations.Item(index).exemptionRequests)
      End If

      Dim exemptionRequest As New ExemptionRequest
      exemptionRequest.key = policyError.key
      exemptionRequests.Add(exemptionRequest)
      allOperations.Item(index).exemptionRequests = exemptionRequests.ToArray
    Else
      ' Policy violation error is not exemptable, remove this
      ' operation from the list of operations.
      operationsToBeRemoved.Add(allOperations.Item(index))
    End If
  Else
    ' This is not a policy violation error, remove this operation
    ' from the list of operations.
    operationsToBeRemoved.Add(allOperations.Item(index))
  End If
Next

Atualizar as operações com solicitações de isenção

Para reenviar as operações que falharam devido a erros de violação de política isentos, você precisará adicionar uma ou mais ExemptionRequests ao conjunto exemptionRequests da operação.

Uma ExemptionRequest tem apenas um atributo, PolicyViolationKey, que é composto por:

  • uma string que identifica o nome da política;
  • uma string que identifica o texto que viola a política.

Uma vantagem é que essas informações podem ser consultadas em todos os atributos PolicyViolationError encontrados. Conforme mostrado no snippet de código a seguir, você pode usar o atributo key de cada PolicyViolationError para o key do ExemptionRequest correspondente.

Java

private static boolean handleApiError(
    ApiError error, int operationIndex, AdGroupAdOperation operation) {
  // Determine if the operation can be resubmitted with an exemption request.
  boolean isExemptableError = false;
  PolicyViolationError policyViolationError = null;
  if (error instanceof PolicyViolationError) {
    policyViolationError = (PolicyViolationError) error;
    ExpandedTextAd expandedTextAd = (ExpandedTextAd) operation.getOperand().getAd();
    System.out.printf(
        "Ad with headline '%s - %s' violated %s policy '%s'.%n",
        expandedTextAd.getHeadlinePart1(),
        expandedTextAd.getHeadlinePart2(),
        policyViolationError.getIsExemptable() ? "exemptable" : "non-exemptable",
        policyViolationError.getExternalPolicyName());
    isExemptableError = policyViolationError.getIsExemptable();
  }

  if (isExemptableError) {
    // Add exemption request to the operation.
    System.out.printf(
        "Adding exemption request for policy name '%s' on text '%s' to operation at index %d.%n",
        policyViolationError.getKey().getPolicyName(),
        policyViolationError.getKey().getViolatingText(),
        operationIndex);
    ExemptionRequest exemptionRequest = new ExemptionRequest();
    exemptionRequest.setKey(policyViolationError.getKey());

    List<ExemptionRequest> exemptionRequests =
        (operation.getExemptionRequests() == null)
            ? new ArrayList<ExemptionRequest>()
            : new ArrayList<>(Arrays.asList(operation.getExemptionRequests()));
    exemptionRequests.add(exemptionRequest);
    operation.setExemptionRequests(
        exemptionRequests.toArray(new ExemptionRequest[exemptionRequests.size()]));
  }
  return isExemptableError;
}

CSharp

// Handle policy violation errors.
if (apiError is PolicyViolationError) {
  PolicyViolationError policyError = (PolicyViolationError) apiError;

  if (policyError.isExemptable) {
    // If the policy violation error is exemptable, add an exemption
    // request.
    List<ExemptionRequest> exemptionRequests = new List<ExemptionRequest>();
    if (allOperations[index].exemptionRequests != null) {
      exemptionRequests.AddRange(allOperations[index].exemptionRequests);
    }

    ExemptionRequest exemptionRequest = new ExemptionRequest();
    exemptionRequest.key = policyError.key;
    exemptionRequests.Add(exemptionRequest);
    allOperations[index].exemptionRequests = exemptionRequests.ToArray();
  } else {
    // Policy violation error is not exemptable, remove this
    // operation from the list of operations.
    operationsToBeRemoved.Add(allOperations[index]);
  }
} else {
  // This is not a policy violation error, remove this operation
  // from the list of operations.
  operationsToBeRemoved.Add(allOperations[index]);
}

Python

def HandleAPIError(error, operation):
  """Makes an exemption for exemptable PolicyViolationErrors.

  Args:
    error: the error associated with the given operation.
    operation: the operation associated with the given error.

  Returns:
    A boolean that is True if the given error was an exemptable
    PolicyViolationError; otherwise, returns False.
  """
  is_exemptable = False

  # Determine if the operation can be resubmitted with an exemption request.
  if error['ApiError.Type'] == 'PolicyViolationError':
    expanded_text_ad = operation['operand']['ad']
    is_exemptable = (error['isExemptable'] if 'isExemptable' in error else
                     False)
    print ('Ad with headline "%s - %s" violated %s policy "%s".' %
           (expanded_text_ad['headlinePart1'],
            expanded_text_ad['headlinePart2'],
            'exemptable' if is_exemptable else 'non-exemptable',
            error['externalPolicyName']))

  if is_exemptable:
    # Add exemption request to the operation.
    print ('Adding exemption request for policy name "%s" on text "%s".'
           % (error['key']['policyName'], error['key']['violatingText']))
    if 'exemptionRequests' not in operation:
      operation['exemptionRequests'] = []
    operation['exemptionRequests'].append({'key': error['key']})

  return is_exemptable

PHP

private static function handleApiError(
    ApiError $apiError,
    $operationIndex,
    AdGroupAdOperation $operation
) {
    $isExemptableError = false;
    $policyViolationError = null;

    $expandedTextAd = $operation->getOperand()->getAd();
    if ($apiError instanceof PolicyViolationError) {
        printf(
            "Ad with headline '%s - %s' violated %s policy '%s'.\n",
            $expandedTextAd->getHeadlinePart1(),
            $expandedTextAd->getHeadlinePart2(),
            $apiError->getIsExemptable() ? 'exemptable' : 'non-exemptable',
            $apiError->getExternalPolicyName()
        );
        $isExemptableError = $apiError->getIsExemptable();
    }

    if ($isExemptableError) {
        // Add exemption request to the operation.
        printf(
            "Adding exemption request for policy name '%s' on text '%s' to operation at index %d.\n",
            $apiError->getKey()->getPolicyName(),
            $apiError->getKey()->getViolatingText(),
            $operationIndex
        );
        if ($operation->getExemptionRequests() === null) {
            $exemptionRequests = [];
        } else {
            $exemptionRequests = $operation->getExemptionRequests();
        }
        $exemptionRequests[] = new ExemptionRequest($apiError->getKey());
        $operation->setExemptionRequests($exemptionRequests);
    }

    return $isExemptableError;
}

Perl

if ($error->get_ApiError__Type() =~ "PolicyViolationError") {
  printf "Ad with headline '%s' violated '%s' policy '%s'.\n",
    $operation->get_operand()->get_ad()->get_headlinePart1(),
    $error->get_isExemptable ? 'exemptable' : 'non-exemptable',
    $error->get_externalPolicyName();

  if ($error->get_isExemptable()) {
    # Add exemption request to the operation.
    printf(
      "Adding exemption request for policy name '%s' on text " .
        "'%s'.\n",
      $error->get_key()->get_policyName(),
      $error->get_key()->get_violatingText());
    $operation->set_exemptionRequests([
        new Google::Ads::AdWords::v201802::ExemptionRequest(
          {key => $error->get_key()})]);
  } else {
    # Remove non-exemptable operation.
    print "Removing from the request.\n";
    push @operation_indicies_to_remove, $operation_index;
  }
} else {
  # Non-policy error returned, remove ad.
  print "Removing from the request.\n";
  push @operation_indicies_to_remove, $operation_index;
}

Ruby

def process_api_error(error, operation)
  is_exemptable = error[:is_exemptable]

  puts "Ad with headline '%s - %s' violated %s policy '%s'." %
      [operation[:operand][:ad][:headline_part1],
      operation[:operand][:ad][:headline_part2],
      is_exemptable ? 'exemptable' : 'non-exemptable',
      error[:external_policy_name]]

  if is_exemptable
    # Add exemption request to the operation.
    puts "Adding exemption request for policy name '%s' on text '%s'." %
        [error[:key][:policy_name], error[:key][:violating_text]]
    unless operation[:exemption_requests]
      operation[:exemption_requests] = []
    end
    operation[:exemption_requests] << {
      :key => error[:key]
    }
  end
end

VB.NET

' Handle policy violation errors.
If TypeOf apiError Is PolicyViolationError Then
  Dim policyError As PolicyViolationError = CType(apiError, PolicyViolationError)

  If policyError.isExemptable Then
    ' If the policy violation error is exemptable, add an exemption
    ' request.
    Dim exemptionRequests As New List(Of ExemptionRequest)
    If (Not allOperations.Item(index).exemptionRequests Is Nothing) Then
      exemptionRequests.AddRange(allOperations.Item(index).exemptionRequests)
    End If

    Dim exemptionRequest As New ExemptionRequest
    exemptionRequest.key = policyError.key
    exemptionRequests.Add(exemptionRequest)
    allOperations.Item(index).exemptionRequests = exemptionRequests.ToArray
  Else
    ' Policy violation error is not exemptable, remove this
    ' operation from the list of operations.
    operationsToBeRemoved.Add(allOperations.Item(index))
  End If
Else
  ' This is not a policy violation error, remove this operation
  ' from the list of operations.
  operationsToBeRemoved.Add(allOperations.Item(index))
End If

Reenviar as operações modificadas

Usando o exemplo, neste ponto você terá os seguintes exemplares de AdGroupAdOperation:

  • Um AdGroupAdOperation do anúncio A com uma única solicitação de isenção: o nome de política "pharma" e o texto que viola a política retirados do primeiro PolicyViolationError.
  • Um AdGroupAdOperation do anúncio B com duas solicitações de isenção: uma com o nome de política "pharma" e o texto que viola a política retirados do segundo PolicyViolationError e outra com o nome de política "nonstandard_punctuation" e o texto que viola a política retirados do terceiro PolicyViolationError.

O AdGroupAdOperation do anúncio C foi descartado, porque o PolicyViolationError dele não era passível de isenção.

Depois de fazer tudo isso, você pode enviar os exemplares de AdGroupAdOperation modificados dos anúncios A e B. Essas operações terão êxito e resultarão em dois novos anúncios com análise pendente.

Monitorar o status de aprovação de cada anúncio ou palavra-chave

Como ocorre com outros anúncios novos, é possível enviar solicitações AdGroupAdService.get() ou AdGroupAdService.query() periodicamente que incluem o campo AdGroupCreativeApprovalStatus. Isso é útil para monitorar o anúncio e conferir se ele acabou sendo aprovado ou rejeitado.

Exemplos de código

Cada biblioteca cliente contém dois exemplos de código relacionados a violações de políticas:

  • Lidar com erros de violação de política: este exemplo mostra como identificar e reenviar AdGroupAdOperations que falharam devido a violações de políticas passíveis de isenção.
  • Validar anúncio de texto: este exemplo mostra como enviar anúncios para validação usando o cabeçalho SOAP validateOnly, descrito no guia sobre estrutura da chamada de API.

Enviar comentários sobre…

Precisa de ajuda? Acesse nossa página de suporte.