Register for one of our Google Ads API Migration Workshops (October 5, 2021 - October 14, 2021)

Requesting Exemption for Ads

The steps for requesting exemption for ads are as follows:

  1. Store all the ignorable policy topic included in PolicyTopicEntry, which is stored inside PolicyFindingDetails, returned when your first attempt to mutate an ad failed.
  2. Send a mutate request to create or update the ad again by including the stored ignorable policy topics.

In this guide, we create an expanded text ad as an example, but the steps for requesting exemption is the same for all ad types and similar for all mutates (create & update).

Store all ignorable policy topics

The error details for ads will be included in PolicyFindingDetails, which in turn stores a list of PolicyTopicEntry objects.

In this step, you need to store the topic field of each PolicyTopicEntry:

Java

private List<String> fetchIgnorablePolicyTopics(GoogleAdsException gae) {
  System.out.println("Google Ads failure details:");

  // Creates a list to store the result.
  List<String> ignorableTopics = new ArrayList<>();

  // Searches all errors for ignorable policy topics.
  for (GoogleAdsError error : gae.getGoogleAdsFailure().getErrorsList()) {
    // Supports sending exemption request for the policy finding error only.
    if (error.getErrorCode().getErrorCodeCase() != ErrorCodeCase.POLICY_FINDING_ERROR) {
      throw gae;
    }

    // Shows some information about the error encountered.
    System.out.printf("\t%s: %s%n", error.getErrorCode().getErrorCodeCase(), error.getMessage());

    // Checks policy finding details for ignorable policy topics.
    if (error.getDetails() != null) {
      PolicyFindingDetails policyFindingDetails = error.getDetails().getPolicyFindingDetails();
      if (policyFindingDetails != null) {
        System.out.println("\tPolicy finding details:");
        // Shows all the policy topics for the current error.
        for (PolicyTopicEntry policyTopicEntry :
            policyFindingDetails.getPolicyTopicEntriesList()) {
          // Adds this topic to the result.
          ignorableTopics.add(policyTopicEntry.getTopic());
          System.out.printf("\t\tPolicy topic name: '%s'%n", policyTopicEntry.getTopic());
          System.out.printf("\t\tPolicy topic entry type: '%s'%n", policyTopicEntry.getType());
          // For the sake of brevity, we exclude printing "policy topic evidences" and
          // "policy topic constraints" here. You can fetch those data by calling:
          // - policyTopicEntry.getEvidences()
          // - policyTopicEntry.getConstraints()
        }
      }
    }
  }
  return ignorableTopics;
}
      
      

C#

private static string[] FetchIgnorablePolicyTopics(GoogleAdsException ex)
{
    List<string> ignorablePolicyTopics = new List<string>(); ;

    Console.WriteLine("Google Ads failure details:");
    foreach (GoogleAdsError error in ex.Failure.Errors)
    {
        if (error.ErrorCode.ErrorCodeCase != ErrorCode.ErrorCodeOneofCase.PolicyFindingError)
        {
            throw ex;
        }
        if (error.Details != null && error.Details.PolicyFindingDetails != null)
        {
            PolicyFindingDetails details = error.Details.PolicyFindingDetails;
            Console.WriteLine($"- Policy finding details:");

            foreach (PolicyTopicEntry entry in details.PolicyTopicEntries)
            {
                ignorablePolicyTopics.Add(entry.Topic);
                Console.WriteLine($"  - Policy topic name: '{entry.Topic}");
                Console.WriteLine($"  - Policy topic entry type: '{entry.Type}");
                // For the sake of brevity, we exclude printing "policy topic evidences"
                // and "policy topic constraints" here. You can fetch those data by
                // calling:
                // - entry.Evidences
                // - entry.Constraints
            }
        }
    }
    return ignorablePolicyTopics.ToArray();
}
      
      

PHP

private static function fetchIgnorablePolicyTopics(GoogleAdsException $googleAdsException)
{
    $ignorablePolicyTopics = [];

    printf("Google Ads failure details:%s", PHP_EOL);
    foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) {
        /** @var GoogleAdsError $error */
        if ($error->getErrorCode()->getErrorCode() !== 'policy_finding_error') {
            // This example supports sending exemption request for the policy finding error
            // only.
            throw $googleAdsException;
        }

        printf(
            "\t%s: %s%s",
            $error->getErrorCode()->getErrorCode(),
            $error->getMessage(),
            PHP_EOL
        );
        if (
            !is_null($error->getDetails())
            && !is_null($error->getDetails()->getPolicyFindingDetails())
        ) {
            $policyFindingDetails = $error->getDetails()->getPolicyFindingDetails();
            printf("\tPolicy finding details:%s", PHP_EOL);

            foreach ($policyFindingDetails->getPolicyTopicEntries() as $policyTopicEntry) {
                /** @var PolicyTopicEntry $policyTopicEntry */
                $ignorablePolicyTopics[] = $policyTopicEntry->getTopic();
                printf(
                    "\t\tPolicy topic name: '%s'%s",
                    $policyTopicEntry->getTopic(),
                    PHP_EOL
                );
                printf(
                    "\t\tPolicy topic entry type: '%s'%s",
                    PolicyTopicEntryType::name($policyTopicEntry->getType()),
                    PHP_EOL
                );
                // For the sake of brevity, we exclude printing "policy topic evidences" and
                // "policy topic constraints" here. You can fetch those data by calling:
                // - $policyTopicEntry->getEvidences()
                // - $policyTopicEntry->getConstraints()
            }
        }
    }
    return $ignorablePolicyTopics;
}
      
      

Python

def _fetch_ignorable_policy_topics(client, googleads_exception):
    """Collects all ignorable policy topics to be sent for exemption request.

    Args:
        client: The GoogleAds client instance.
        googleads_exception: The exception that contains the policy
            violation(s).

    Returns:
        A list of ignorable policy topics.
    """
    ignorable_policy_topics = []

    print("Google Ads failure details:")
    for error in googleads_exception.failure.errors:
        if (
            error.error_code.policy_finding_error
            != client.get_type(
                "PolicyFindingErrorEnum"
            ).PolicyFindingError.POLICY_FINDING
        ):
            print(
                "This example supports sending exemption request for the "
                "policy finding error only."
            )
            raise googleads_exception

        print(f"\t{error.error_code.policy_finding_error}: {error.message}")

        if (
            error.details is not None
            and error.details.policy_finding_details is not None
        ):
            policy_finding_details = error.details.policy_finding_details
            print("\tPolicy finding details:")

            for (
                policy_topic_entry
            ) in policy_finding_details.policy_topic_entries:
                ignorable_policy_topics.append(policy_topic_entry.topic)
                print(f"\t\tPolicy topic name: '{policy_topic_entry.topic}'")
                print(
                    f"\t\tPolicy topic entry type: '{policy_topic_entry.type_}'"
                )
                # For the sake of brevity, we exclude printing "policy topic
                # evidences" and "policy topic constraints" here. You can fetch
                # those data by calling:
                # - policy_topic_entry.evidences
                # - policy_topic_entry.constraints

    return ignorable_policy_topics
      
      

Ruby

def fetch_ignorable_policy_topics(exception)
  ignorable_policy_topics = []

  exception.failure.errors.each do |error|
    if error.error_code.policy_finding_error != :POLICY_FINDING
      puts "Non-policy finding error found. Aborting."
      raise exception
    end
    puts "#{error.error_code.policy_finding_error}: #{error.message}"

    error&.details&.policy_finding_details&.policy_topic_entries.each do |entry|
      ignorable_policy_topics << entry.topic
      puts "\tPolicy topic name: #{entry.topic}"
      puts "\tPolicy topic entry type: #{entry.type}"
    end
  end

  ignorable_policy_topics
end
      
      

Perl

sub fetch_ignorable_policy_topics {
  my $google_ads_exception = shift;

  my $ignorable_policy_topics = [];

  printf "Google Ads failure details:\n";
  foreach
    my $error (@{$google_ads_exception->get_google_ads_failure()->{errors}})
  {
    if ([keys %{$error->{errorCode}}]->[0] ne "policyFindingError") {
      # This example supports sending exemption request for the policy finding
      # error only.
      die $google_ads_exception->get_message();
    }

    printf "\t%s: %s\n", [keys %{$error->{errorCode}}]->[0], $error->{message};

    if ($error->{details}{policyFindingDetails}) {
      my $policy_finding_details = $error->{details}{policyFindingDetails};
      printf "\tPolicy finding details:\n";

      foreach my $policy_topic_entry (
        @{$policy_finding_details->{policyTopicEntries}})
      {
        push @$ignorable_policy_topics, $policy_topic_entry->{topic};
        printf
          "\t\tPolicy topic name: '%s'\n",
          $policy_topic_entry->{topic};
        printf "\t\tPolicy topic entry type: '%s'\n",
          $policy_topic_entry->{type};
        # For the sake of brevity, we exclude printing "policy topic evidences" and
        # "policy topic constraints" here. You can fetch those data by calling:
        # - $policy_topic_entry->{evidences}
        # - $policy_topic_entry->{constraints}
      }
    }
  }

  return $ignorable_policy_topics;
}
      
      

Send another mutate request by including ignorable policy topics

  1. Create an object of PolicyValidationParameter.
  2. Set stored ignorable policy topics to the ignorable_policy_topics field of the created PolicyValidationParameter.
  3. Set the created PolicyValidationParameter to the policy_validation_parameter field of an AdGroupAdOperation in the case of a creation or an AdOperation in the case of an update.
  4. Send a mutate request with the created operation using AdGroupAdService.MutateAdGroupAds in the case of a creation or AdService.MutateAds in the case of an update.

Java

private void requestExemption(
    List<String> ignorablePolicyTopics,
    AdGroupAdServiceClient client,
    AdGroupAdOperation operation,
    long customerID) {
  System.out.println(
      "Trying to add an expanded text ad again by requesting exemption for its policy"
          + " violations.");
  // Converts the operation back to a builder.
  AdGroupAdOperation.Builder operationBuilder = operation.toBuilder();

  // Adds the exemption request.
  operationBuilder
      .getPolicyValidationParameterBuilder()
      .addAllIgnorablePolicyTopics(ignorablePolicyTopics);

  // Sends the request back to the API.
  MutateAdGroupAdsResponse response =
      client.mutateAdGroupAds(
          String.valueOf(customerID), ImmutableList.of(operationBuilder.build()));

  // Shows the newly added ad resource name.
  System.out.printf(
      "Successfully added an expanded text ad with resource name '%s' by requesting a policy"
          + " violation exemption.%n",
      response.getResults(0).getResourceName());
}
      
      

C#

private static void RequestExemption(long customerId, AdGroupAdServiceClient service,
    AdGroupAdOperation operation, string[] ignorablePolicyTopics)
{
    Console.WriteLine("Try adding an expanded text ad again by requesting exemption for " +
        "its policy violations.");
    PolicyValidationParameter validationParameter = new PolicyValidationParameter();
    validationParameter.IgnorablePolicyTopics.AddRange(ignorablePolicyTopics);
    operation.PolicyValidationParameter = validationParameter;

    MutateAdGroupAdsResponse response = service.MutateAdGroupAds(
        customerId.ToString(), new[] { operation });
    Console.WriteLine($"Successfully added an expanded text ad with resource name " +
        $"'{response.Results[0].ResourceName}' by requesting for policy violation " +
        $"exemption.");
}
      
      

PHP

private static function requestExemption(
    int $customerId,
    AdGroupAdServiceClient $adGroupAdServiceClient,
    AdGroupAdOperation $adGroupAdOperation,
    array $ignorablePolicyTopics
) {
    print "Try adding an expanded text ad again by requesting exemption for its policy"
        . " violations." . PHP_EOL;
    $adGroupAdOperation->setPolicyValidationParameter(
        new PolicyValidationParameter(['ignorable_policy_topics' => $ignorablePolicyTopics])
    );
    $response = $adGroupAdServiceClient->mutateAdGroupAds(
        $customerId,
        [$adGroupAdOperation]
    );
    printf(
        "Successfully added an expanded text ad 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_ad_service_client,
    ad_group_ad_operation,
    ignorable_policy_topics,
):
    """Sends exemption requests for creating an expanded text ad.

    Args:
        customer_id: The customer ID for which to add the expanded text ad.
        ad_group_ad_service_client: The AdGroupAdService client instance.
        ad_group_ad_operation: The AdGroupAdOperation that returned policy
            violation(s).
        ignorable_policy_topics: The extracted list of policy topic entries.
    """
    print(
        "Attempting to add an expanded text ad again by requesting exemption "
        "for its policy violations."
    )
    ad_group_ad_operation.policy_validation_parameter.ignorable_policy_topics.extend(
        ignorable_policy_topics
    )
    response = ad_group_ad_service_client.mutate_ad_group_ads(
        customer_id=customer_id, operations=[ad_group_ad_operation]
    )
    print(
        "Successfully added an expanded text ad with resource name "
        f"'{response.results[0].resource_name}' for policy violation "
        "exemption."
    )
      
      

Ruby

def request_exemption(
    client, customer_id, ad_group_ad_service, ad_group_ad_operation, ignorable_policy_topics)
  # Add all the found ignorable policy topics to the operation.
  ad_group_ad_operation.policy_validation_parameter =
      client.resource.policy_validation_parameter do |pvp|
    pvp.ignorable_policy_topics.push(
      *ignorable_policy_topics
    )
  end
  response = ad_group_ad_service.mutate_ad_group_ads(
    customer_id: customer_id,
    operations: [ad_group_ad_operation],
  )
  puts "Successfully added an expanded text ad with resource name " \
    "#{response.results.first.resource_name} for policy violation exception."
end
      
      

Perl

sub request_exemption {
  my ($api_client, $customer_id, $ad_group_ad_operation,
    $ignorable_policy_topics)
    = @_;

  print
    "Try adding an expanded text ad again by requesting exemption for its " .
    "policy violations.\n";

  $ad_group_ad_operation->{policyValidationParameter} =
    Google::Ads::GoogleAds::V8::Common::PolicyValidationParameter->new(
    {ignorablePolicyTopics => $ignorable_policy_topics});

  my $ad_group_ads_response = $api_client->AdGroupAdService()->mutate({
      customerId => $customer_id,
      operations => [$ad_group_ad_operation]});

  printf "Successfully added an expanded text ad with resource name '%s' by " .
    "requesting for policy violation exemption.\n",
    $ad_group_ads_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: