Requesting Exemption for Keywords

The steps for requesting exemption for keywords are as follows:

  1. Store all the exemptible policy violation keys included in PolicyViolationDetails, returned when your first attempt to create a keyword failed.
  2. Send a mutate request to create the keyword again by including the stored exemptible policy violation keys.

Store all exemptible policy violation keys

The error details for keywords will be included in PolicyViolationDetails, which in turn stores the key field whose value is an object of PolicyViolationKey.

Collect all exemptible policy violation keys to be used in the next step:

Java

private List<PolicyViolationKey> extractExemptiblePolicyViolationKeys(
    GoogleAdsException googleAdsException) {
  List<PolicyViolationKey> exemptibleKeys = new ArrayList<>();
  System.out.println("Google Ads failure details:");
  for (GoogleAdsError googleAdsError : googleAdsException.getGoogleAdsFailure().getErrorsList()) {
    System.out.printf("\t%s: %s%n", googleAdsError.getErrorCode(), googleAdsError.getMessage());
    if (googleAdsError.hasDetails() && googleAdsError.getDetails().hasPolicyViolationDetails()) {
      PolicyViolationDetails policyViolationDetails =
          googleAdsError.getDetails().getPolicyViolationDetails();
      System.out.println("\tPolicy violation details:");
      System.out.printf(
          "\t\tExternal policy name: '%s'%n", policyViolationDetails.getExternalPolicyName());
      System.out.printf(
          "\t\tExternal policy description: '%s'%n",
          policyViolationDetails.getExternalPolicyDescription());
      System.out.printf("\t\tIs exemptible? '%s'%n", policyViolationDetails.getIsExemptible());
      if (policyViolationDetails.getIsExemptible() && policyViolationDetails.hasKey()) {
        PolicyViolationKey policyViolationKey = policyViolationDetails.getKey();
        exemptibleKeys.add(policyViolationKey);
        System.out.println("\t\tPolicy violation key:");
        System.out.printf("\t\t\tName: '%s'%n", policyViolationKey.getPolicyName());
        System.out.printf("\t\t\tViolating text: '%s'%n", policyViolationKey.getViolatingText());
      }
    }
  }
  return exemptibleKeys;
}

C#

private static PolicyViolationKey[] FetchExemptPolicyViolationKeys(GoogleAdsException ex)
{
    bool isFullyExemptable = true;
    List<PolicyViolationKey> exemptPolicyViolationKeys = new List<PolicyViolationKey>();

    Console.WriteLine("Google Ads failure details:");
    foreach (GoogleAdsError error in ex.Failure.Errors)
    {
        if (error.ErrorCode.ErrorCodeCase !=
            ErrorCode.ErrorCodeOneofCase.PolicyViolationError)
        {
            Console.WriteLine("No exemption request is sent because there are other " +
                "non-policy related errors thrown.");
            throw ex;
        }
        if (error.Details != null && error.Details.PolicyViolationDetails != null)
        {
            PolicyViolationDetails details = error.Details.PolicyViolationDetails;
            Console.WriteLine($"- Policy violation details:");

            Console.WriteLine(" - Policy violation details:");
            Console.WriteLine($"   - External policy name: '{details.ExternalPolicyName}'");
            Console.WriteLine($"   - External policy description: " +
                $"'{details.ExternalPolicyDescription}'");
            Console.WriteLine($"   - Is exemptable: '{details.IsExemptible}'");

            if (details.IsExemptible && details.Key != null)
            {
                PolicyViolationKey key = details.Key;
                Console.WriteLine($"   - Policy violation key:");
                Console.WriteLine($"     - Name: {key.PolicyName}");
                Console.WriteLine($"     - Violating Text: {key.ViolatingText}");
                exemptPolicyViolationKeys.Add(key);
            }
            else
            {
                isFullyExemptable = false;
            }
        }
    }

    if (!isFullyExemptable)
    {
        Console.WriteLine("No exemption request is sent because your keyword " +
            "contained some non-exemptible policy violations.");
        throw ex;
    }
    return exemptPolicyViolationKeys.ToArray();
}
// [END HandleKeywordPolicyViolations]


PHP

private static function fetchExemptPolicyViolationKeys(GoogleAdsException $googleAdsException)
{
    $exemptPolicyViolationKeys = [];

    printf("Google Ads failure details:%s", PHP_EOL);
    foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) {
        /** @var GoogleAdsError $error */
        printf(
            "\t%s: %s%s",
            $error->getErrorCode()->getErrorCode(),
            $error->getMessage(),
            PHP_EOL
        );
        if (
            !is_null($error->getDetails())
            && !is_null($error->getDetails()->getPolicyViolationDetails())
        ) {
            $policyViolationDetails = $error->getDetails()->getPolicyViolationDetails();
            printf("\tPolicy violation details:%s", PHP_EOL);
            printf(
                "\t\tExternal policy name: '%s'%s",
                $policyViolationDetails->getExternalPolicyName(),
                PHP_EOL
            );
            printf(
                "\t\tExternal policy description: '%s'%s",
                $policyViolationDetails->getExternalPolicyDescription(),
                PHP_EOL
            );
            printf(
                "\t\tIs exemptible? '%s'%s",
                $policyViolationDetails->getIsExemptible() ? 'yes' : 'no',
                PHP_EOL
            );

            if (
                $policyViolationDetails->getIsExemptible() &&
                !is_null($policyViolationDetails->getKey())
            ) {
                $policyViolationDetailsKey = $policyViolationDetails->getKey();
                $exemptPolicyViolationKeys[] = $policyViolationDetailsKey;
                printf("\t\tPolicy violation key:%s", PHP_EOL);
                printf(
                    "\t\t\tName: '%s'%s",
                    $policyViolationDetailsKey->getPolicyName(),
                    PHP_EOL
                );
                printf(
                    "\t\t\tViolating text: '%s'%s",
                    $policyViolationDetailsKey->getViolatingText(),
                    PHP_EOL
                );
            } else {
                print "No exemption request is sent because your keyword contained some "
                    . "non-exemptible policy violations." . PHP_EOL;
                throw $googleAdsException;
            }
        } else {
            print "No exemption request is sent because there are other non-policy related "
                . "errors thrown." . PHP_EOL;
            throw $googleAdsException;
        }
    }
    return $exemptPolicyViolationKeys;
}

Python

def _fetch_exempt_policy_violation_keys(google_ads_exception):
    """Collects all policy violation keys that can be exempted.

    Args:
        google_ads_exception: The exception to check for policy violation(s).

    Returns:
        A list of policy violation keys.
    """
    exempt_policy_violation_keys = []

    print("Google Ads failure details:")
    for error in google_ads_exception.failure.errors:
        print(f"\t{error.error_code}: {error.message}")

        if (
            error.details is not None
            and error.details.policy_violation_details is not None
        ):
            policy_violation_details = error.details.policy_violation_details
            print(
                "\tPolicy violation details:\n"
                f"\t\tExternal policy name: '{policy_violation_details}'\n"
                "\t\tExternal policy description: "
                f"'{policy_violation_details.external_policy_description}'\n"
                f"\t\tIs exemptible? '{policy_violation_details.is_exemptible}'"
            )

            if (
                policy_violation_details.is_exemptible
                and policy_violation_details.key is not None
            ):
                exempt_policy_violation_keys.append(
                    policy_violation_details.key
                )
                print(
                    f"\t\tPolicy violation key: {policy_violation_details.key}"
                )
                print(
                    f"\t\t\tName: '{policy_violation_details.key.policy_name}'"
                    "\t\t\tViolating text: "
                    f"'{policy_violation_details.key.violating_text}'"
                )
            else:
                print(
                    "No exemption request is sent because your keyword "
                    "contained some non-exemptible policy violations."
                )
                raise google_ads_exception
        else:
            print(
                "No exemption request is sent because there are non-policy "
                "related errors thrown."
            )
            raise google_ads_exception

    return exempt_policy_violation_keys

Ruby

def fetch_exempt_policy_violation_keys(exception)
  exempt_policy_violation_keys = []

  exception.failure.errors.each do |error|
    details = error.details.policy_violation_details
    puts "Policy violation details:"
    puts "\tExternal policy name: #{details.external_policy_name}"
    puts "\tExternal policy description:\n#{details.external_policy_description}"
    puts "\tIs exemptible: #{details.is_exemptible}"

    if details.is_exemptible && !details.key.nil?
      exempt_policy_violation_keys << details.key
      puts "Policy violation key:"
      puts "\tPolicy Name: #{details.key.policy_name}"
      puts "\tViolating Text: #{details.key.violating_text}"
    else
      puts "No exemption request will be sent because your keyword contained "\
        "some non-exemptible policy violations."
    end
  end

  exempt_policy_violation_keys
end

Perl

sub fetch_exempt_policy_violation_keys {
  my $google_ads_exception = shift;

  my $exempt_policy_violation_keys = [];

  print "Google Ads failure details:\n";
  foreach
    my $error (@{$google_ads_exception->get_google_ads_failure()->{errors}})
  {
    printf "\t%s: %s\n", [keys %{$error->{errorCode}}]->[0], $error->{message};

    if ($error->{details}{policyViolationDetails}) {
      my $policy_violation_details = $error->{details}{policyViolationDetails};
      printf "\tPolicy violation details:\n";
      printf "\t\tExternal policy name: '%s'\n",
        $policy_violation_details->{externalPolicyName};
      printf
        "\t\tExternal policy description: '%s'\n",
        $policy_violation_details->{externalPolicyDescription};
      printf
        "\t\tIs exemptible? '%s'\n",
        $policy_violation_details->{isExemptible} ? "yes" : "no";

      if (  $policy_violation_details->{isExemptible}
        and $policy_violation_details->{key})
      {
        my $policy_violation_details_key = $policy_violation_details->{key};
        push @$exempt_policy_violation_keys, $policy_violation_details_key;

        printf "\t\tPolicy violation key:\n";
        printf "\t\t\tName: '%s'\n",
          $policy_violation_details_key->{policyName};
        printf
          "\t\t\tViolating text: '%s'\n",
          $policy_violation_details_key->{violatingText};
      }
    }
  }

  return $exempt_policy_violation_keys;
}

Send another mutate request by including exemptible policy violation keys

  1. Set all exemptible policy violation keys to the exempt_policy_violation_keys field of an ad group criterion operation.
  2. Send a mutate request for creating the keyword again.

Java

// Tries sending exemption requests for creating the keyword. However, if your keyword
// contains many policy violations, but not all of them are exemptible, the request will not
// be sent.
if (exemptibleKeys.size() == errorCount) {
  System.out.println(
      "Attempting to add the keyword again by requesting exemption for its policy"
          + " violations.");
  // Creates a modified version of the operation with the exempt policy violation keys.
  operation = operation.toBuilder().addAllExemptPolicyViolationKeys(exemptibleKeys).build();

  // Tries sending the mutate request again.
  MutateAdGroupCriteriaResponse response =
      adGroupCriterionServiceClient.mutateAdGroupCriteria(
          String.valueOf(customerId), ImmutableList.of(operation));
  System.out.printf(
      "Successfully added a keyword with resource name '%s' by requesting "
          + "policy violation exemptions.%n",
      response.getResults(0).getResourceName());
} else {

C#

private static void RequestExemption(
    long customerId, AdGroupCriterionServiceClient service,
    AdGroupCriterionOperation operation, PolicyViolationKey[] exemptPolicyViolationKeys)
{
    Console.WriteLine("Try adding a keyword again by requesting exemption for its policy "
        + "violations.");
    PolicyValidationParameter validationParameter = new PolicyValidationParameter();
    validationParameter.ExemptPolicyViolationKeys.AddRange(exemptPolicyViolationKeys);
    operation.ExemptPolicyViolationKeys.AddRange(exemptPolicyViolationKeys);

    MutateAdGroupCriteriaResponse response = service.MutateAdGroupCriteria(
        customerId.ToString(), new[] { operation });
    Console.WriteLine($"Successfully added a keyword with resource name " +
        $"'{response.Results[0].ResourceName}' by requesting for policy violation " +
        $"exemption.");
}

PHP

private static function requestExemption(
    int $customerId,
    AdGroupCriterionServiceClient $adGroupCriterionServiceClient,
    AdGroupCriterionOperation $adGroupCriterionOperation,
    array $exemptPolicyViolationKeys
) {
    print "Try adding a keyword again by requesting exemption for its policy"
        . " violations." . PHP_EOL;
    $adGroupCriterionOperation->setExemptPolicyViolationKeys($exemptPolicyViolationKeys);
    $response = $adGroupCriterionServiceClient->mutateAdGroupCriteria(
        $customerId,
        [$adGroupCriterionOperation]
    );
    printf(
        "Successfully added a keyword with resource name '%s' by requesting for"
        . " policy violation exemption.%s",
        $response->getResults()[0]->getResourceName(),
        PHP_EOL
    );
}

Python

def _request_exemption(
    customer_id,
    ad_group_criterion_service,
    ad_group_criterion_operation,
    exempt_policy_violation_keys,
):
    """Sends exemption requests for creating a keyword.

    Args:
        customer_id: The customer ID for which to add the expanded text ad.
        ad_group_criterion_service: The AdGroupCriterionService client instance.
        ad_group_criterion_operation: The AdGroupCriterionOperation for which
            to request exemption.
        exempt_policy_violation_keys: The exemptible policy violation keys.
    """
    print(
        "Attempting to add a keyword again by requesting exemption for its "
        "policy violations."
    )
    ad_group_criterion_operation.exempt_policy_violation_keys.extend(
        exempt_policy_violation_keys
    )
    response = ad_group_criterion_service.mutate_ad_group_criteria(
        customer_id, [ad_group_criterion_operation]
    )
    print(
        "Successfully added a keyword with resource name "
        f"'{response.results[0].resource_name}' by requesting a policy "
        "violation exemption."
    )
    # [END handle_keyword_policy_violations_1]

Ruby

def request_exemption(
    client,
    customer_id,
    ad_group_criterion_service,
    ad_group_criterion_operation,
    exempt_policy_violation_keys
)
  # Add all the found ignorable policy topics to the operation.
  ad_group_criterion_operation.exempt_policy_violation_keys.push(
    *exempt_policy_violation_keys
  )
  response = ad_group_criterion_service.mutate_ad_group_criteria(
    customer_id: customer_id,
    operations: [ad_group_criterion_operation],
  )
  puts "Successfully added a keyword with resource name " \
    "#{response.results.first.resource_name} for policy violation exception."
end

Perl

sub request_exemption {
  my ($api_client, $customer_id, $ad_group_criterion_operation,
    $exempt_policy_violation_keys)
    = @_;

  print "Try adding a keyword again by requesting exemption for its " .
    "policy violations.\n";

  $ad_group_criterion_operation->{exemptPolicyViolationKeys} =
    $exempt_policy_violation_keys;

  my $ad_group_criteria_response =
    $api_client->AdGroupCriterionService()->mutate({
      customerId => $customer_id,
      operations => [$ad_group_criterion_operation]});

  printf "Successfully added a keyword with resource name '%s' by requesting " .
    "for policy violation exemption.\n",
    $ad_group_criteria_response->{results}[0]{resourceName};
}

Code examples

The ErrorHandling folder of each client library contains the following code example that shows how to use this feature: