Java
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.ads.googleads.examples.errorhandling ; import com.beust.jcommander.Parameter ; import com.google.ads.googleads.examples.utils.ArgumentNames ; import com.google.ads.googleads.examples.utils.CodeSampleParams ; import com.google.ads.googleads.lib.GoogleAdsClient ; import com.google.ads.googleads.v21.common.KeywordInfo ; import com.google.ads.googleads.v21.common.PolicyViolationKey ; import com.google.ads.googleads.v21.enums.AdGroupCriterionStatusEnum.AdGroupCriterionStatus ; import com.google.ads.googleads.v21.enums.KeywordMatchTypeEnum.KeywordMatchType ; import com.google.ads.googleads.v21.errors.GoogleAdsError ; import com.google.ads.googleads.v21.errors.GoogleAdsException ; import com.google.ads.googleads.v21.errors.PolicyViolationDetails ; import com.google.ads.googleads.v21.resources.AdGroupCriterion ; import com.google.ads.googleads.v21.services.AdGroupCriterionOperation ; import com.google.ads.googleads.v21.services.AdGroupCriterionServiceClient ; import com.google.ads.googleads.v21.services.MutateAdGroupCriteriaResponse ; import com.google.ads.googleads.v21.utils.ResourceNames ; import com.google.common.collect.ImmutableList ; import java.io.FileNotFoundException ; import java.io.IOException ; import java.util.ArrayList ; import java.util.List ; /** * Demonstrates how to request an exemption for policy violations of a keyword. * * <p>The example uses an exemptible policy-violating keyword by default. If you use a keyword that * contains non-exemptible policy violations, it will not be sent with exemptions requested and you * will still fail to create a keyword. * * <p>If you specify a keyword that doesn't violate any policies, this example will just add the * keyword as usual, similar to what the AddKeywords example does. * * <p>When you send a request to add a keyword after requesting a policy exemption for that keyword, * the request will pass as if you were adding a non-violating keyword. */ public class HandleKeywordPolicyViolations { private static class HandleKeywordPolicyViolationsParams extends CodeSampleParams { @Parameter ( names = ArgumentNames . CUSTOMER_ID , required = true ) private Long customerId ; @Parameter ( names = ArgumentNames . AD_GROUP_ID , required = true ) private Long adGroupId ; @Parameter ( names = ArgumentNames . KEYWORD_TEXT ) private String keywordText = "medication" ; } public static void main ( String [] args ) throws IOException { HandleKeywordPolicyViolationsParams params = new HandleKeywordPolicyViolationsParams (); if ( ! params . parseArguments ( args )) { // Either pass the required parameters for this example on the command line, or insert them // into the code here. See the parameter class definition above for descriptions. params . customerId = Long . parseLong ( "INSERT_CUSTOMER_ID_HERE" ); params . adGroupId = Long . parseLong ( "INSERT_AD_GROUP_ID_HERE" ); // Optional: Specify a keywordText here, or the default specified above will be used. // params.keywordText = "INSERT_KEYWORD_TEXT_HERE"; } GoogleAdsClient googleAdsClient = null ; try { googleAdsClient = GoogleAdsClient . newBuilder (). fromPropertiesFile (). build (); } catch ( FileNotFoundException fnfe ) { System . err . printf ( "Failed to load GoogleAdsClient configuration from file. Exception: %s%n" , fnfe ); System . exit ( 1 ); } catch ( IOException ioe ) { System . err . printf ( "Failed to create GoogleAdsClient. Exception: %s%n" , ioe ); System . exit ( 1 ); } try { new HandleKeywordPolicyViolations () . runExample ( googleAdsClient , params . customerId , params . adGroupId , params . keywordText ); } catch ( GoogleAdsException gae ) { // GoogleAdsException is the base class for most exceptions thrown by an API request. // Instances of this exception have a message and a GoogleAdsFailure that contains a // collection of GoogleAdsErrors that indicate the underlying causes of the // GoogleAdsException. System . err . printf ( "Request ID %s failed due to GoogleAdsException. Underlying errors:%n" , gae . getRequestId ()); int i = 0 ; for ( GoogleAdsError googleAdsError : gae . getGoogleAdsFailure (). getErrorsList ()) { System . err . printf ( " Error %d: %s%n" , i ++ , googleAdsError ); } System . exit ( 1 ); } } /** * Runs the example. * * @param googleAdsClient the Google Ads API client. * @param customerId the client customer ID. * @param adGroupId the ID of the ad group to add a keyword to. * @param keywordText the keyword text to add. * @throws GoogleAdsException if an API request failed with one or more service errors. */ private void runExample ( GoogleAdsClient googleAdsClient , long customerId , Long adGroupId , String keywordText ) { try ( AdGroupCriterionServiceClient adGroupCriterionServiceClient = googleAdsClient . getLatestVersion (). createAdGroupCriterionServiceClient ()) { // Configures the keyword text and match type settings. KeywordInfo keywordInfo = KeywordInfo . newBuilder () . setText ( keywordText ) . setMatchType ( KeywordMatchType . EXACT ) . build (); // Constructs an ad group criterion using the keyword text info above. AdGroupCriterion adGroupCriterion = AdGroupCriterion . newBuilder () . setAdGroup ( ResourceNames . adGroup ( customerId , adGroupId )) . setStatus ( AdGroupCriterionStatus . ENABLED ) . setKeyword ( keywordInfo ) . build (); // Constructs an operation to create the ad group criterion. AdGroupCriterionOperation operation = AdGroupCriterionOperation . newBuilder (). setCreate ( adGroupCriterion ). build (); // Tries sending a mutate request to add the keyword. List<PolicyViolationKey> exemptibleKeys = new ArrayList <> (); int errorCount = 0 ; try { MutateAdGroupCriteriaResponse response = adGroupCriterionServiceClient . mutateAdGroupCriteria ( String . valueOf ( customerId ), ImmutableList . of ( operation )); // If the request succeeded, then either the keyword does not require a policy exemption or // a policy exemption was previously submitted for the keyword. In either case, returns and // skips the remaining portion of this example that resubmits with an exemption request. System . out . printf ( "Successfully added a keyword with resource name '%s'. No exemptions needed.%n" , response . getResults ( 0 ). getResourceName ()); return ; } catch ( GoogleAdsException e ) { exemptibleKeys = extractExemptiblePolicyViolationKeys ( e ); errorCount = e . getGoogleAdsFailure (). getErrorsCount (); } // 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 { System . out . println ( "No exemption request was sent because either:" ); System . out . println ( "1) your keyword contained some non-exemptible policy violations, or" ); System . out . println ( "2) other non-policy related errors were thrown" ); } } } /** * Collects all policy violation keys that can be exempted for sending an exemption request later. * * @param googleAdsException the exception to extract the keys from. * @return the list of extracted exemptible keys. */ 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#
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using CommandLine ; using Google.Ads.Gax.Examples ; using Google.Ads.GoogleAds.Lib ; using Google.Ads.GoogleAds.V21.Common ; using Google.Ads.GoogleAds.V21.Errors ; using Google.Ads.GoogleAds.V21.Resources ; using Google.Ads.GoogleAds.V21.Services ; using System ; using System.Collections.Generic ; using static Google . Ads . GoogleAds . V21 . Enums . AdGroupCriterionStatusEnum . Types ; using static Google . Ads . GoogleAds . V21 . Enums . KeywordMatchTypeEnum . Types ; namespace Google.Ads.GoogleAds.Examples.V21 { /// <summary> /// This code example demonstrates how to request an exemption for policy violations of a /// keyword. Note that the example uses an exemptible policy-violating keyword by default. /// If you use a keyword that contains non-exemptible policy violations, they will not be /// sent for exemption request and you will still fail to create a keyword. /// If you specify a keyword that doesn't violate any policies, this example will just add the /// keyword as usual, similar to what the AddKeywords example does. /// Note that once you've requested policy exemption for a keyword, when you send a request for /// adding it again, the request will pass like when you add a non-violating keyword. /// </summary> public class HandleKeywordPolicyViolations : ExampleBase { /// <summary> /// Command line options for running the <see cref="HandleKeywordPolicyViolations"/> example. /// </summary> public class Options : OptionsBase { /// <summary> /// The customer ID for which the call is made. /// </summary> [Option("customerId", Required = true, HelpText = "The customer ID for which the call is made.")] public long CustomerId { get ; set ; } /// <summary> /// ID of the ad group to which keywords are added. /// </summary> [Option("adGroupId", Required = true, HelpText = "ID of the ad group to which keywords are added.")] public long AdGroupId { get ; set ; } /// <summary> /// The keyword text to add to the ad group. /// </summary> [Option("keywordText", Required = false, HelpText = "The keyword text to add to the ad group.")] public string KeywordText { get ; set ; } } /// <summary> /// Main method, to run this code example as a standalone application. /// </summary> /// <param name="args">The command line arguments.</param> public static void Main ( string [] args ) { Options options = ExampleUtilities . ParseCommandLine<Options> ( args ); HandleKeywordPolicyViolations codeExample = new HandleKeywordPolicyViolations (); Console . WriteLine ( codeExample . Description ); codeExample . Run ( new GoogleAdsClient (), options . CustomerId , options . AdGroupId , options . KeywordText ); } /// <summary> /// The default keyword to be used if keyword is not provided. /// </summary> private const string DEFAULT_KEYWORD = "medication" ; /// <summary> /// Returns a description about the code example. /// </summary> public override string Description = > "This code example demonstrates how to request an exemption for policy violations of " + "a keyword. Note that the example uses an exemptible policy-violating keyword by " + "default. If you use a keyword that contains non-exemptible policy violations, they " + "will not be sent for exemption request and you will still fail to create a keyword. " + "If you specify a keyword that doesn't violate any policies, this example will just " + "add the keyword as usual, similar to what the AddKeywords example does. Note that " + "once you've requested policy exemption for a keyword, when you send a request for " + "adding it again, the request will pass like when you add a non-violating keyword." ; /// <summary> /// Runs the code example. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The customer ID for which the call is made.</param> /// <param name="adGroupId">ID of the ad group to which keywords are added.</param> /// <param name="keywordText">The keyword text to add to the ad group.</param> public void Run ( GoogleAdsClient client , long customerId , long adGroupId , string keywordText ) { // Get the AdGroupCriterionServiceClient. AdGroupCriterionServiceClient service = client . GetService ( Services . V21 . AdGroupCriterionService ); if ( string . IsNullOrEmpty ( keywordText )) { keywordText = DEFAULT_KEYWORD ; } // Configures the keyword text and match type settings. KeywordInfo keywordInfo = new KeywordInfo () { Text = keywordText , MatchType = KeywordMatchType . Exact }; // Constructs an ad group criterion using the keyword text info above. AdGroupCriterion adGroupCriterion = new AdGroupCriterion () { AdGroup = ResourceNames . AdGroup ( customerId , adGroupId ), Status = AdGroupCriterionStatus . Paused , Keyword = keywordInfo }; AdGroupCriterionOperation operation = new AdGroupCriterionOperation () { Create = adGroupCriterion }; try { try { // Try sending a mutate request to add the keyword. MutateAdGroupCriteriaResponse response = service . MutateAdGroupCriteria ( customerId . ToString (), new [] { operation }); Console . WriteLine ( $"Added a keyword with resource name " + $"'{response.Results[0].ResourceName}'." ); } catch ( GoogleAdsException ex ) { PolicyViolationKey [] exemptPolicyViolationKeys = FetchExemptPolicyViolationKeys ( ex ); // Try sending exemption requests for creating a keyword. However, if your // keyword contains many policy violations, but not all of them are exemptible, // the request will not be sent. RequestExemption ( customerId , service , operation , exemptPolicyViolationKeys ); } } catch ( GoogleAdsException e ) { Console . WriteLine ( "Failure:" ); Console . WriteLine ( $"Message: {e.Message}" ); Console . WriteLine ( $"Failure: {e.Failure}" ); Console . WriteLine ( $"Request ID: {e.RequestId}" ); throw ; } } /// <summary> /// Collects all policy violation keys that can be exempted for sending a exemption /// request later. /// </summary> /// <param name="ex">The Google Ads exception.</param> /// <returns>The exemptible policy violation keys.</returns> 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 (); } /// <summary> /// Sends exemption requests for creating a keyword. /// </summary> /// <param name="customerId">The customer ID for which the call is made.</param> /// <param name="service">The ad group criterion service.</param> /// <param name="operation">The ad group criterion operation to request exemption for. /// </param> /// <param name="exemptPolicyViolationKeys">The exemptable policy violation keys.</param> 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
< ?php /** * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Google\Ads\GoogleAds\Examples\ErrorHandling; require __DIR__ . '/../../vendor/autoload.php'; use GetOpt\GetOpt; use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames; use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser; use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder; use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClient; use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClientBuilder; use Google\Ads\GoogleAds\Lib\V21\GoogleAdsException; use Google\Ads\GoogleAds\Util\V21\ResourceNames; use Google\Ads\GoogleAds\V21\Common\KeywordInfo; use Google\Ads\GoogleAds\V21\Common\PolicyViolationKey; use Google\Ads\GoogleAds\V21\Enums\AdGroupCriterionStatusEnum\AdGroupCriterionStatus; use Google\Ads\GoogleAds\V21\Enums\KeywordMatchTypeEnum\KeywordMatchType; use Google\Ads\GoogleAds\V21\Errors\GoogleAdsError; use Google\Ads\GoogleAds\V21\Resources\AdGroupCriterion; use Google\Ads\GoogleAds\V21\Services\AdGroupCriterionOperation; use Google\Ads\GoogleAds\V21\Services\Client\AdGroupCriterionServiceClient; use Google\Ads\GoogleAds\V21\Services\MutateAdGroupCriteriaRequest; use Google\ApiCore\ApiException; /** * This example demonstrates how to request an exemption for policy violations of a keyword. * Note that the example uses an exemptible policy-violating keyword by default. If you use a * keyword that contains non-exemptible policy violations, they will not be sent for exemption * request and you will still fail to create a keyword. * If you specify a keyword that doesn't violate any policies, this example will just add the * keyword as usual, similar to what the AddKeywords example does. * * Note that once you've requested policy exemption for a keyword, when you send a request for * adding it again, the request will pass like when you add a non-violating keyword. */ class HandleKeywordPolicyViolations { private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE'; private const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE'; // Specify the keyword text here or the default specified below will be used. private const KEYWORD_TEXT = 'medication'; public static function main() { // Either pass the required parameters for this example on the command line, or insert them // into the constants above. $options = (new ArgumentParser())->parseCommandArguments([ ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT, ArgumentNames::AD_GROUP_ID => GetOpt::REQUIRED_ARGUMENT, ArgumentNames::KEYWORD_TEXT => GetOpt::OPTIONAL_ARGUMENT ]); // Generate a refreshable OAuth2 credential for authentication. $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build(); // Construct a Google Ads client configured from a properties file and the // OAuth2 credentials above. $googleAdsClient = (new GoogleAdsClientBuilder())->fromFile() ->withOAuth2Credential($oAuth2Credential) ->build(); try { self::runExample( $googleAdsClient, $options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID, $options[ArgumentNames::AD_GROUP_ID] ?: self::AD_GROUP_ID, $options[ArgumentNames::KEYWORD_TEXT] ?: self::KEYWORD_TEXT ); } catch (GoogleAdsException $googleAdsException) { printf( "Request with ID '%s' has failed.%sGoogle Ads failure details:%s", $googleAdsException->getRequestId(), PHP_EOL, PHP_EOL ); foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) { /** @var GoogleAdsError $error */ printf( "\t%s: %s%s", $error->getErrorCode()->getErrorCode(), $error->getMessage(), PHP_EOL ); } exit(1); } catch (ApiException $apiException) { printf( "ApiException was thrown with message '%s'.%s", $apiException->getMessage(), PHP_EOL ); exit(1); } } /** * Runs the example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param int $adGroupId the ad group ID to add a keyword to * @param string $keywordText the keyword text to add */ public static function runExample( GoogleAdsClient $googleAdsClient, int $customerId, int $adGroupId, string $keywordText ) { // Configures the keyword text and match type settings. $keywordInfo = new KeywordInfo([ 'text' => $keywordText, 'match_type' => KeywordMatchType::EXACT ]); // Constructs an ad group criterion using the keyword text info above. $adGroupCriterion = new AdGroupCriterion([ 'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId), 'status' => AdGroupCriterionStatus::ENABLED, 'keyword' => $keywordInfo ]); $adGroupCriterionOperation = new AdGroupCriterionOperation(); $adGroupCriterionOperation->setCreate($adGroupCriterion); $adGroupCriterionServiceClient = $googleAdsClient->getAdGroupCriterionServiceClient(); try { // Try sending a mutate request to add the keyword. $response = $adGroupCriterionServiceClient->mutateAdGroupCriteria( MutateAdGroupCriteriaRequest::build($customerId, [$adGroupCriterionOperation]) ); printf( "Added a keyword with resource name '%s'.%s", $response->getResults()[0]->getResourceName(), PHP_EOL ); } catch (GoogleAdsException $googleAdsException) { // Try sending exemption requests for creating a keyword. However, if your keyword // contains many policy violations, but not all of them are exemptible, the request // will not be sent. $exemptPolicyViolationKeys = self::fetchExemptPolicyViolationKeys($googleAdsException); self::requestExemption( $customerId, $adGroupCriterionServiceClient, $adGroupCriterionOperation, $exemptPolicyViolationKeys ); } } /** * Collects all policy violation keys that can be exempted for sending a exemption request * later. * * @param GoogleAdsException $googleAdsException the Google Ads exception * @return PolicyViolationKey[] the exemptible policy violation keys */ 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; } /** * Sends exemption requests for creating a keyword. * * @param int $customerId the customer ID * @param AdGroupCriterionServiceClient $adGroupCriterionServiceClient the ad group criterion * service API client * @param AdGroupCriterionOperation $adGroupCriterionOperation the ad group criterion operation * to request exemption for * @param PolicyViolationKey[] $exemptPolicyViolationKeys the exemptible policy violation keys */ 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( MutateAdGroupCriteriaRequest::build($customerId, [$adGroupCriterionOperation]) ); printf( "Successfully added a keyword with resource name '%s' by requesting for" . " policy violation exemption.%s", $response->getResults()[0]->getResourceName(), PHP_EOL ); } } HandleKeywordPolicyViolations::main();
Python
#!/usr/bin/env python # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Demonstrates how to request an exemption for policy violations of a keyword. Note that the example uses an exemptible policy-violating keyword by default. If you use a keyword that contains non-exemptible policy violations, they will not be sent for exemption request, and you will still fail to create a keyword. If you specify a keyword that doesn't violate any policies, this example will just add the keyword as usual, similar to what the AddKeywords example does. Note that once you've requested policy exemption for a keyword, when you send a request for adding it again, the request will pass like when you add a non-violating keyword. """ import argparse import sys from typing import Any , List , Optional , Tuple from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException from google.ads.googleads.v21.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient , ) from google.ads.googleads.v21.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation , ) from google.ads.googleads.v21.common.types.policy import PolicyViolationKey def main ( client : GoogleAdsClient , customer_id : str , ad_group_id : str , keyword_text : str , ) - > None : """Demonstrates how to request an exemption for keyword policy violations. Args: client: The Google Ads client. customer_id: The customer ID for which to add the keyword. ad_group_id: The ad group ID to which to add keyword. keyword_text: The keyword text to add. """ ad_group_criterion_service : AdGroupCriterionServiceClient = ( client . get_service ( "AdGroupCriterionService" ) ) googleads_exception : Optional [ GoogleAdsException ] ad_group_criterion_operation : AdGroupCriterionOperation ( googleads_exception , ad_group_criterion_operation , ) = create_keyword_criterion ( client , ad_group_criterion_service , customer_id , ad_group_id , keyword_text , ) try : # Try sending exemption requests for creating a keyword. However, if # your keyword contains many policy violations, but not all of them are # exemptible, the request will not be sent. if googleads_exception is not None : exempt_policy_violation_keys : List [ PolicyViolationKey ] = ( fetch_exempt_policy_violation_keys ( googleads_exception ) ) request_exemption ( customer_id , ad_group_criterion_service , ad_group_criterion_operation , exempt_policy_violation_keys , ) except GoogleAdsException as ex : print ( f "Request with ID ' { ex . request_id } ' failed with status " f "' { ex . error . code () . name } ' and includes the following errors:" ) for error in ex . failure . errors : print ( f " \t Error with message ' { error . message } '." ) if error . location : for field_path_element in error . location . field_path_elements : print ( f " \t\t On field: { field_path_element . field_name } " ) sys . exit ( 1 ) def create_keyword_criterion ( client : GoogleAdsClient , ad_group_criterion_service : AdGroupCriterionServiceClient , customer_id : str , ad_group_id : str , keyword_text : str , ) - > Tuple [ Optional [ GoogleAdsException ], AdGroupCriterionOperation ]: """Attempts to add a keyword criterion to an ad group. Args: client: The GoogleAds client instance. ad_group_criterion_service: The AdGroupCriterionService client instance. customer_id: The customer ID for which to add the expanded text ad. ad_group_id: The ad group ID to which to add an expanded text ad. keyword_text: The keyword text to add. Returns: The GoogleAdsException that occurred (or None if the operation was successful) and the modified operation. """ # Constructs an ad group criterion using the keyword text provided. ad_group_criterion_operation : AdGroupCriterionOperation = client . get_type ( "AdGroupCriterionOperation" ) ad_group_criterion : Any = ad_group_criterion_operation . create ad_group_criterion . ad_group = client . get_service ( "AdGroupService" ) . ad_group_path ( customer_id , ad_group_id ) ad_group_criterion . status = client . enums . AdGroupCriterionStatusEnum . ENABLED ad_group_criterion . keyword . text = keyword_text ad_group_criterion . keyword . match_type = ( client . enums . KeywordMatchTypeEnum . EXACT ) try : # Try sending a mutate request to add the keyword. response : Any = ad_group_criterion_service . mutate_ad_group_criteria ( customer_id = customer_id , operations = [ ad_group_criterion_operation ] ) except GoogleAdsException as googleads_exception : # Return the exception in order to extract keyword violation details. return googleads_exception , ad_group_criterion_operation # Report that the mutate request was completed successfully. print ( "Added a keyword with resource name " f "' { response . results [ 0 ] . resource_name } '." ) return None , ad_group_criterion_operation def fetch_exempt_policy_violation_keys ( googleads_exception : GoogleAdsException , ) - > List [ PolicyViolationKey ]: """Collects all policy violation keys that can be exempted. Args: googleads_exception: The exception to check for policy violation(s). Returns: A list of policy violation keys. """ exempt_policy_violation_keys : List [ PolicyViolationKey ] = [] print ( "Google Ads failure details:" ) for error in googleads_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 ( " \t Policy violation details: \n " f " \t\t External policy name: ' { policy_violation_details } ' \n " " \t\t External policy description: " f "' { policy_violation_details . external_policy_description } ' \n " f " \t\t Is 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\t Policy violation key: { policy_violation_details . key } " ) print ( f " \t\t\t Name: ' { policy_violation_details . key . policy_name } '" " \t\t\t Violating 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 googleads_exception else : print ( "No exemption request is sent because there are non-policy " "related errors thrown." ) raise googleads_exception return exempt_policy_violation_keys def request_exemption ( customer_id : str , ad_group_criterion_service : AdGroupCriterionServiceClient , ad_group_criterion_operation : AdGroupCriterionOperation , exempt_policy_violation_keys : List [ PolicyViolationKey ], ) - > None : """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 : Any = ad_group_criterion_service . mutate_ad_group_criteria ( customer_id = customer_id , operations = [ ad_group_criterion_operation ] ) print ( "Successfully added a keyword with resource name " f "' { response . results [ 0 ] . resource_name } ' by requesting a policy " "violation exemption." ) if __name__ == "__main__" : parser = argparse . ArgumentParser ( description = "Demonstrates how to request an exemption for policy " "violations of a keyword." ) # The following argument(s) should be provided to run the example. parser . add_argument ( "-c" , "--customer_id" , type = str , required = True , help = "The Google Ads customer ID." , ) parser . add_argument ( "-a" , "--ad_group_id" , type = str , required = True , help = "The ad group ID to which to add an expanded text ad." , ) parser . add_argument ( "-k" , "--keyword_text" , type = str , required = False , default = "medication" , help = "Specify the keyword text here or use the default keyword " "'medication'." , ) args = parser . parse_args () # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client : GoogleAdsClient = GoogleAdsClient . load_from_storage ( version = "v21" ) main ( googleads_client , args . customer_id , args . ad_group_id , args . keyword_text )
Ruby
# Encoding: utf-8 # # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Demonstrates how to request an exemption for policy violations of a keyword. # # Note that the example uses an exemptible policy-violating keyword by default. # If you use a keyword that contains non-exemptible policy violations, they # will not be sent for exemption request and you will still fail to create a # keyword. If you specify a keyword that doesn't violate any policies, this # example will just add the keyword as usual, similar to what the AddKeywords # example does. # # Note that once you've requested policy exemption for a keyword, when you send # a request for adding it again, the request will pass like when you add a # non-violating keyword. require 'optparse' require 'google/ads/google_ads' require 'date' def handle_keyword_policy_violations ( customer_id , ad_group_id , keyword_text ) # GoogleAdsClient will read a config file from # ENV['HOME']/google_ads_config.rb when called without parameters client = Google :: Ads :: GoogleAds :: GoogleAdsClient . new ad_group_criterion_service = client . service . ad_group_criterion exception , ad_group_criterion_operation = create_keyword_criterion ( client , ad_group_criterion_service , customer_id , ad_group_id , keyword_text , ) unless exception . nil? exempt_policy_violation_keys = fetch_exempt_policy_violation_keys ( exception ) request_exemption ( client , customer_id , ad_group_criterion_service , ad_group_criterion_operation , exempt_policy_violation_keys , ) end end def create_keyword_criterion ( client , ad_group_criterion_service , customer_id , ad_group_id , keyword_text ) ad_group_criterion_operation = client . operation . create_resource . ad_group_criterion do | agc | agc . ad_group = client . path . ad_group ( customer_id , ad_group_id ) agc . status = :ENABLED agc . keyword = client . resource . keyword_info do | ki | ki . match_type = :EXACT ki . text = keyword_text end end ignorable_policy_topics = [] begin ad_group_criterion_service . mutate_ad_group_criteria ( customer_id : customer_id , operations : [ ad_group_criterion_operation ] , ) rescue Google :: Ads :: GoogleAds :: Errors :: GoogleAdsError = > e return e , ad_group_criterion_operation end return nil , ad_group_criterion_operation end 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 " \t External policy name: #{ details . external_policy_name } " puts " \t External policy description: \n #{ details . external_policy_description } " puts " \t Is exemptible: #{ details . is_exemptible } " if details . is_exemptible && ! details . key . nil? exempt_policy_violation_keys << details . key puts "Policy violation key:" puts " \t Policy Name: #{ details . key . policy_name } " puts " \t Violating 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 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 if __FILE__ == $PROGRAM_NAME options = {} # The following parameter(s) should be provided to run the example. You can # either specify these by changing the INSERT_XXX_ID_HERE values below, or on # the command line. # # Parameters passed on the command line will override any parameters set in # code. # # Running the example with -h will print the command line usage. options [ :customer_id ] = 'INSERT_CUSTOMER_ID_HERE' options [ :ad_group_id ] = 'INSERT_AD_GROUP_ID_HERE' options [ :keyword_text ] = 'INSERT_KEYWORD_TEXT_HERE' OptionParser . new do | opts | opts . banner = sprintf ( 'Usage: ruby %s [options]' , File . basename ( __FILE__ )) opts . separator '' opts . separator 'Options:' opts . on ( '-C' , '--customer-id CUSTOMER-ID' , String , 'Customer ID' ) do | v | options [ :customer_id ] = v end opts . on ( '-A' , '--ad-group-id AD-GROUP-ID' , String , 'Ad Group ID' ) do | v | options [ :ad_group_id ] = v end opts . on ( '-k' , '--keyword-text KEYWORD-TEXT' , String , 'Keyword' ) do | v | options [ :keyword_text ] = v end opts . separator '' opts . separator 'Help:' opts . on_tail ( '-h' , '--help' , 'Show this message' ) do puts opts exit end end . parse! begin handle_keyword_policy_violations ( options . fetch ( :customer_id ) . tr ( "-" , "" ), options . fetch ( :ad_group_id ), options . fetch ( :keyword_text ), ) rescue Google :: Ads :: GoogleAds :: Errors :: GoogleAdsError = > e e . failure . errors . each do | error | STDERR . printf ( "Error with message: %s \n " , error . message ) if error . location error . location . field_path_elements . each do | field_path_element | STDERR . printf ( " \t On field: %s \n " , field_path_element . field_name ) end end error . error_code . to_h . each do | k , v | next if v == :UNSPECIFIED STDERR . printf ( " \t Type: %s \n\t Code: %s \n " , k , v ) end end raise end end
Perl
#!/usr/bin/perl -w # # Copyright 2019, Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This example demonstrates how to request an exemption for policy violations # of a keyword. Note that the example uses an exemptible policy-violating # keyword by default. If you use a keyword that contains non-exemptible policy # violations, they will not be sent for exemption request and you will still # fail to create a keyword. # If you specify a keyword that doesn't violate any policies, this example will # just add the keyword as usual, similar to what the add_keywords.pl example does. # # Note that once you've requested policy exemption for a keyword, when you send # a request for adding it again, the request will pass like when you add a # non-violating keyword. use strict ; use warnings ; use utf8 ; use FindBin qw($Bin) ; use lib "$Bin/../../lib" ; use Google::Ads::GoogleAds::Client ; use Google::Ads::GoogleAds::Utils::GoogleAdsHelper ; use Google::Ads::GoogleAds::V21::Resources::AdGroupCriterion ; use Google::Ads::GoogleAds::V21::Common::KeywordInfo ; use Google::Ads::GoogleAds::V21::Enums::KeywordMatchTypeEnum qw(EXACT) ; use Google::Ads::GoogleAds::V21::Enums::AdGroupCriterionStatusEnum qw(ENABLED) ; use Google::Ads::GoogleAds::V21::Services::AdGroupCriterionService::AdGroupCriterionOperation ; use Google::Ads::GoogleAds::V21::Utils::ResourceNames ; use Getopt::Long qw(:config auto_help) ; use Pod::Usage ; use Cwd qw(abs_path) ; # The following parameter(s) should be provided to run the example. You can # either specify these by changing the INSERT_XXX_ID_HERE values below, or on # the command line. # # Parameters passed on the command line will override any parameters set in # code. # # Running the example with -h will print the command line usage. my $customer_id = "INSERT_CUSTOMER_ID_HERE" ; my $ad_group_id = "INSERT_AD_GROUP_ID_HERE" ; my $keyword_text = "medication" ; sub handle_keyword_policy_violations { my ( $api_client , $customer_id , $ad_group_id , $keyword_text ) = @_ ; # Configure the keyword text and match type settings. my $keyword_info = Google::Ads::GoogleAds::V21::Common:: KeywordInfo - > new ({ text = > $keyword_text , matchType = > EXACT }); # Construct an ad group criterion using the keyword info above. my $ad_group_criterion = Google::Ads::GoogleAds::V21::Resources:: AdGroupCriterion - > new ({ adGroup = > Google::Ads::GoogleAds::V21::Utils::ResourceNames:: ad_group ( $customer_id , $ad_group_id ), status = > ENABLED , keyword = > $keyword_info }); # Create an ad group criterion operation. my $ad_group_criterion_operation = Google::Ads::GoogleAds::V21::Services::AdGroupCriterionService:: AdGroupCriterionOperation - > new ({ create = > $ad_group_criterion }); # Try sending a mutate request to add the keyword. my $response = $api_client - > AdGroupCriterionService () - > mutate ({ customerId = > $customer_id , operations = > [ $ad_group_criterion_operation ]}); if ( $response - > isa ( "Google::Ads::GoogleAds::GoogleAdsException" )) { my $exempt_policy_violation_keys = fetch_exempt_policy_violation_keys ( $response ); # Try sending exemption requests for creating a keyword. However, if your # keyword contains many policy violations, but not all of them are exemptible, # the request will not be sent. if ( @$exempt_policy_violation_keys == @ { $response - > get_google_ads_failure () - > { errors }}) { request_exemption ( $api_client , $customer_id , $ad_group_criterion_operation , $exempt_policy_violation_keys ); } else { print "No exemption request is sent because 1) your keyword contained " . "some non-exemptible policy violations or 2) there are other " . "non-policy related errors thrown.\n" ; } } else { printf "Added a keyword with resource name '%s'.\n" , $response - > { results }[ 0 ]{ resourceName }; } return 1 ; } # Collects all policy violation keys that can be exempted for sending a exemption # request later. 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 ; } # Sends exemption requests for creating a keyword. 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 }; } # Don't run the example if the file is being included. if ( abs_path ( $0 ) ne abs_path ( __FILE__ )) { return 1 ; } # Get Google Ads Client, credentials will be read from ~/googleads.properties. my $api_client = Google::Ads::GoogleAds:: Client - > new (); # By default examples are set to die on any server returned fault. $api_client - > set_die_on_faults ( 0 ); # Parameters passed on the command line will override any parameters set in code. GetOptions ( "customer_id=s" = > \ $customer_id , "ad_group_id=i" = > \ $ad_group_id , "keyword_text=s" = > \ $keyword_text ); # Print the help message if the parameters are not initialized in the code nor # in the command line. pod2usage ( 2 ) if not check_params ( $customer_id , $ad_group_id , $keyword_text ); # Call the example. handle_keyword_policy_violations ( $api_client , $customer_id =~ s/-//g r , $ad_group_id , $keyword_text ); =pod =head1 NAME handle_keyword_policy_violations =head1 DESCRIPTION This example demonstrates how to request an exemption for policy violations of a keyword. Note that the example uses an exemptible policy-violating keyword by default. If you use a keyword that contains non-exemptible policy violations, they will not be sent for exemption request and you will still fail to create a keyword. If you specify a keyword that doesn't violate any policies, this example will just add the keyword as usual, similar to what the add_keywords.pl example does. Note that once you've requested policy exemption for a keyword, when you send a request for adding it again, the request will pass like when you add a non-violating keyword. =head1 SYNOPSIS handle_keyword_policy_violations.pl [options] -help Show the help message. -customer_id The Google Ads customer ID. -ad_group_id The ad group ID. -keyword_text [optional] The keyword to be added to the ad group. =cut