ポリシー適用免除のリクエスト

適用免除をリクエストすると、ポリシー違反の原因となるキーワードや広告に対する審査リクエストを自動的に送信できます。

たとえば、この機能は次のような状況で利用できます。

  • 広告に一般的ではない句読点が含まれているが、業界では標準的な用法である場合。
  • 広告グループのキーワードに医療用語が含まれているが、広告主様(とユーザー)がその用語の用法が AdWords のポリシーに準拠していて、詳しい審査が必要であると確信している場合。

このような状況で、広告またはキーワードを作成しようとすると、1 回目は失敗して PolicyViolationError が発生します。

広告とキーワードの exemptionRequests コレクションを指定している場合は、広告とキーワードが自動的に送信され、審査されます。審査の結果、承認された場合は、ADD オペレーションを使った広告またはキーワードの再送信が正常に行われます。

重要: 適用免除のリクエストを追加して PolicyViolationError が発生した場合に、広告やキーワードを機械的に再送信しないでください。該当の広告やキーワードが広告掲載のポリシーに準拠していて、詳しい審査が必要であると確信している場合にのみ再送信してください。広告やキーワードが繰り返し広告掲載のポリシーに違反し、不承認になると、AdWords アカウントが強制停止される場合があります。

広告が PolicyViolationError なしで正常に送信されたにもかかわらず広告ポリシーの違反が理由で後で不承認になった場合は、詳細は AdGroupAdPolicySummary に記載されています。

以下では、適用免除のリクエストを送信するために必要な手順について説明します。

失敗した各オペレーションのポリシー違反エラーを確認する

1 つの AdGroupAdService.mutate() 呼び出しで、次の 3 つの広告を作成するとします。

  • 広告 A と広告 B の見出しには、同じ医療用語が含まれている
  • また、広告 B の見出しには、標準的ではない句読点が含まれている
  • 広告 C には、標準的ではない文法の広告文が含まれている、または対象のサイトのコンテンツと関係がない

3 つの AdGroupAdOperation を含むサービス呼び出しを送信すると、リクエストが失敗して、次のエラーが発生します。

エラー PolicyViolationError.fieldPath PolicyViolationError.isExemptable PolicyViolationKey.policyName
PolicyViolationError 0 (Ad A) true pharma
PolicyViolationError 1 (Ad B) true pharma
PolicyViolationError 1 (Ad B) true nonstandard_punctuation
PolicyViolationError 2 (Ad C) false unclear_or_inaccurate_ad_text

適用免除可能なポリシー違反の場合はオペレーションを維持する

オペレーション 0 とオペレーション 1 のエラーは適用免除可能なため、適用免除のリクエストを追加して再送信できます。ただし、オペレーション 2 のエラーは適用免除可能ではないため、再送信しても何も起こりません。

次のコード スニペットは、レスポンスのエラーを繰り返し処理し、免除可能なポリシー違反エラーで失敗した各オペレーションのオペレーション index を保持します。

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

適用免除のリクエストを追加してオペレーションを更新する

免除可能なポリシー違反エラーのために失敗したオペレーションを再送信するには、オペレーションの exemptionRequests コレクションに 1 つ以上の ExemptionRequest を追加する必要があります。

ExemptionRequest には、属性 PolicyViolationKey が 1 つだけ含まれ、次の内容で構成されます。

  • ポリシー名を特定する文字列
  • 違反テキストを特定する文字列

発生する各 PolicyViolationError には、この情報が含まれています。次の Java コード スニペットで示すとおり、各 PolicyViolationErrorkey 属性は、対応する ExemptionRequestkey 属性に使用できます。

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

変更したオペレーションを再送信する

この例の場合、この時点で次のような AdGroupAdOperation を使用します。

  • 適用免除のリクエストが 1 つ追加された広告 A の AdGroupAdOperation。リクエストのポリシー名は "pharma"、違反テキストは 1 つ目の PolicyViolationError から取得。
  • 適用免除のリクエストが 2 つ追加された広告 B の AdGroupAdOperation。1 つ目のリクエストのポリシー名は "pharma"、違反テキストは 2 つ目の PolicyViolationError から取得。2 つ目のリクエストのポリシー名は "nonstandard_punctuation"、違反テキストは 3 つ目の PolicyViolationError から取得。

広告 C の AdGroupAdOperation は、PolicyViolationError が適用免除可能ではないため、破棄されます。

このように適切に準備を整えると、広告 A と広告 B の変更した AdGroupAdOperation を送信できます。このオペレーションは正常に行われ、新しい 2 つの広告が審査待ちになります。

各広告またはキーワードの承認状況を確認する

その他の新しい広告と同様に、AdGroupCreativeApprovalStatus フィールドを含む AdGroupAdService.get() または AdGroupAdService.query() リクエストを定期的に送信して、最終的に広告が承認されたかどうかを確認できます。

コードサンプル

各クライアント ライブラリには、ポリシー違反に関連する 2 つのコードサンプルが含まれます。

  • ポリシー違反エラーの処理 - この例では、適用免除可能なポリシー違反が原因で失敗した AdGroupAdOperations を特定して再送信する方法を示しています。
  • テキスト広告の検証 - この例では、API 呼び出しの仕組みについてのガイドで説明されている validateOnly SOAP ヘッダーを使って、検証のために広告を送信する方法を示しています。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。