diff --git a/README.md b/README.md index b4a29572..4aa97c10 100644 --- a/README.md +++ b/README.md @@ -367,6 +367,51 @@ const result = await customer.mutateResources(operations); --- +## Add Policy Exemption Rules + +```ts +import { + resources, + enums, + toMicros, + ResourceNames, + MutateOperation, +} from "google-ads-api"; + +// Ad Group to which you want to add the keyword +const adGroupResourceName = 'customers/123/adGroups/456' + +const keyword = '24 hour locksmith harlem' + +const operations: MutateOperation< + resources.IAdGroupCriterion & { exempt_policy_violation_keys?: google.ads.googleads.v14.common.IPolicyViolationKey[]} +>[] = [ + { + entity: 'ad_group_criterion', + operation: "create", + resource: { + // Keyword with policy violation exemptions + ad_group: adGroupResourceName, + keyword: { + text: '24 hour locksmith harlem', + match_type: enums.KeywordMatchType.PHRASE, + }, + status: enums.AdGroupStatus.ENABLED , + }, + exempt_policy_violation_keys: [ + { + policy_name: 'LOCAL_SERVICES', + violating_text: keyword, + }, + ], + } +]; + +const result = await customer.mutateResources(operations); +``` + +--- + ## Uploading Click Conversions ```ts diff --git a/package.json b/package.json index 82642668..645b583f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "google-ads-api", - "version": "14.1.0", + "version": "14.2.0", "description": "Google Ads API Client Library for Node.js", "repository": "https://github.com/Opteo/google-ads-api", "main": "build/src/index.js", diff --git a/scripts/services.ts b/scripts/services.ts index 794cc052..da69f2e5 100644 --- a/scripts/services.ts +++ b/scripts/services.ts @@ -352,6 +352,11 @@ function buildMutateMethod( ): string { const isUpdate = mutation === "update"; const updateMaskMessageArg = isUpdate ? `, ${requestClass}` : ""; + + const policyViolationArgType = + argName !== "adGroupCriteria" + ? `(${resourceType} | ${requestClass})[]` + : `((${resourceType} & {exempt_policy_violation_keys?: services.AdGroupCriterionOperation['exempt_policy_violation_keys'] } ) | (${requestClass} & {exempt_policy_violation_keys?: services.AdGroupCriterionOperation['exempt_policy_violation_keys'] }))[]`; return ` /** * @description ${mutation} resources of type ${resourceType} @@ -359,9 +364,7 @@ function buildMutateMethod( */ ${mutation}: async ( ${argName}: ${ - mutation === "remove" - ? `${resourceType}[]` - : `(${resourceType} | ${requestClass})[]` + mutation === "remove" ? `${resourceType}[]` : `${policyViolationArgType}` } , options?: MutateOptions ): Promise<${responseType} > => { diff --git a/src/protos/autogen/serviceFactory.ts b/src/protos/autogen/serviceFactory.ts index 8f497041..8fd2e442 100644 --- a/src/protos/autogen/serviceFactory.ts +++ b/src/protos/autogen/serviceFactory.ts @@ -1926,8 +1926,12 @@ export default class ServiceFactory extends Service { */ create: async ( adGroupCriteria: ( - | resources.IAdGroupCriterion - | resources.AdGroupCriterion + | (resources.IAdGroupCriterion & { + exempt_policy_violation_keys?: services.AdGroupCriterionOperation["exempt_policy_violation_keys"]; + }) + | (resources.AdGroupCriterion & { + exempt_policy_violation_keys?: services.AdGroupCriterionOperation["exempt_policy_violation_keys"]; + }) )[], options?: MutateOptions ): Promise => { @@ -2006,8 +2010,12 @@ export default class ServiceFactory extends Service { */ update: async ( adGroupCriteria: ( - | resources.IAdGroupCriterion - | resources.AdGroupCriterion + | (resources.IAdGroupCriterion & { + exempt_policy_violation_keys?: services.AdGroupCriterionOperation["exempt_policy_violation_keys"]; + }) + | (resources.AdGroupCriterion & { + exempt_policy_violation_keys?: services.AdGroupCriterionOperation["exempt_policy_violation_keys"]; + }) )[], options?: MutateOptions ): Promise => { diff --git a/src/service.ts b/src/service.ts index fe1ff977..b1a426bb 100644 --- a/src/service.ts +++ b/src/service.ts @@ -207,7 +207,15 @@ export class Service { const operation = { [mutation.operation ?? "create"]: mutation.resource, }; - if (mutation.operation === "update") { + if ( + mutation.operation === "create" && + //@ts-ignore + mutation?.exempt_policy_violation_keys?.length + ) { + //@ts-ignore + operation.exempt_policy_violation_keys = + mutation.exempt_policy_violation_keys; + } else if (mutation.operation === "update") { // @ts-expect-error Resource operations should have updateMask defined operation.update_mask = getFieldMask(mutation.resource); } @@ -237,7 +245,13 @@ export class Service { [type]: e, operation: type, }; - if (type === "update") { + //@ts-ignore + if (type === "create" && e?.exempt_policy_violation_keys?.length) { + // @ts-expect-error Field required for policy violation exemptions + op.exempt_policy_violation_keys = e.exempt_policy_violation_keys; + //@ts-ignore + delete e.exempt_policy_violation_keys; + } else if (type === "update") { // @ts-expect-error Field required for updates op.update_mask = getFieldMask( // @ts-expect-error Message types have a toObject method diff --git a/src/types.ts b/src/types.ts index 1f0d8a80..347477f0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -118,6 +118,7 @@ export type MutateOperation = { resource: T; entity: fields.Resource; operation?: "create" | "update" | "remove"; + exempt_policy_violation_keys?: services.AdGroupCriterionOperation["exempt_policy_violation_keys"]; } & Partial>; export type PageToken = services.ISearchGoogleAdsResponse["next_page_token"];