diff --git a/src/amazon-advertising.ts b/src/amazon-advertising.ts index 7f9428801..1f5fedc7e 100644 --- a/src/amazon-advertising.ts +++ b/src/amazon-advertising.ts @@ -20,6 +20,7 @@ import { SponsoredProductsSuggestedKeywordsOperation } from './operations/keywor import { PortfolioOperation } from './operations/portfolios/portfolio-operation' import { SponsoredProductsProductAdsOperation } from './operations/product-ads/sponsored-products-product-ads-operation' import { SponsoredBrandsProductTargetingOperation } from './operations/product-targeting/sponsored-brands-product-targeting-operation' +import { SponsoredDisplayTargetingOperation } from './operations/product-targeting/sponsored-display-targeting-operation' import { SponsoredProductsProductTargetingOperation } from './operations/product-targeting/sponsored-products-product-targeting-operation' import { ProfileOperation } from './operations/profiles/profile-operation' import { SponsoredBrandsBidRecommendationsOperation } from './operations/recommendations/sponsored-brands-bid-recommendations-operation' @@ -130,6 +131,11 @@ export class AmazonAdvertising { return this.operationProvider.create(SponsoredBrandsProductTargetingOperation) } + @LazyGetter() + get sponsoredDisplayTargeting() { + return this.operationProvider.create(SponsoredDisplayTargetingOperation) + } + @LazyGetter() get sponsoredProductsProductTargeting() { return this.operationProvider.create(SponsoredProductsProductTargetingOperation) diff --git a/src/errors.ts b/src/errors.ts index 5a50e2f1d..30e1a6e2d 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -76,6 +76,8 @@ export class ResourceNotFoundError extends GenericError {} export class NotAcceptableError extends GenericError {} +export class ForbiddenError extends GenericError {} + export function apiErrorFactory(err: ErrorObject, headers: Headers): GenericError { switch (err.code) { case 'UNAUTHORIZED': @@ -84,6 +86,8 @@ export function apiErrorFactory(err: ErrorObject, headers: Headers): GenericErro return new ResourceNotFoundError(err, headers) case '400': return new BadRequestError(err, headers) + case '403': + return new ForbiddenError(err, headers) case '406': return new NotAcceptableError(err, headers) case '422': diff --git a/src/index.ts b/src/index.ts index 1271c3eb8..5a2a47f44 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,6 +19,7 @@ export * from './operations/keywords/sponsored-products-suggested-keywords-opera export * from './operations/portfolios/portfolio-operation' export * from './operations/product-ads/sponsored-products-product-ads-operation' export * from './operations/product-targeting/sponsored-brands-product-targeting-operation' +export * from './operations/product-targeting/sponsored-display-targeting-operation' export * from './operations/product-targeting/sponsored-products-product-targeting-operation' export * from './operations/profiles/profile-operation' export * from './operations/recommendations/sponsored-brands-bid-recommendations-operation' diff --git a/src/operations/product-targeting/sponsored-display-targeting-operation.ts b/src/operations/product-targeting/sponsored-display-targeting-operation.ts new file mode 100644 index 000000000..85c6fa8a2 --- /dev/null +++ b/src/operations/product-targeting/sponsored-display-targeting-operation.ts @@ -0,0 +1,101 @@ +import { Operation } from '../operation' +import { Decode, DecodeArray } from '../../decorators' +import { AmazonAdTypeURIPrefix } from '../amazon-ad-type-uri-prefix' + +import { + TargetingClauseResponse, + CreateSponsoredDisplayTargetingClausesParams, + TargetId, + SponsoredDisplayTargetingClause, + SponsoredDisplayTargetingClauseExtended, + UpdateSponsoredDisplayTargetingClausesParams, + ListTargetingClausesParams, +} from './types' + +export class SponsoredDisplayTargetingOperation extends Operation { + protected resource = `${this.version}/${AmazonAdTypeURIPrefix.SponsoredDisplay}/targets` + + /** + * Gets a targeting clause specified by identifier. + * + * @param targetId - + * @returns + */ + @Decode(SponsoredDisplayTargetingClause) + public getTargetingClause(targetId: TargetId) { + return this.client.get(`${this.resource}/${targetId}`) + } + + /** + * Gets extended information for a targeting clause. + * + * @param targetId - + * @returns + */ + @Decode(SponsoredDisplayTargetingClauseExtended) + public getTargetingClauseExtended(targetId: TargetId) { + return this.client.get( + `${this.resource}/extended/${targetId}`, + ) + } + + /** + * Creates one or more targeting clauses. + * + * @param params - + * @returns + */ + @DecodeArray(TargetingClauseResponse) + public createTargetingClauses(params: CreateSponsoredDisplayTargetingClausesParams[]) { + return this.client.post(this.resource, params) + } + + /** + * Update one or more targeting clauses. + * + * @param params - + * @returns + */ + @DecodeArray(TargetingClauseResponse) + public updateTargetingClauses(params: UpdateSponsoredDisplayTargetingClausesParams[]) { + return this.client.put(this.resource, params) + } + + /** + * Gets a list of targeting clauses. + * + * @param params - + * @returns + */ + @DecodeArray(SponsoredDisplayTargetingClause) + public listTargetingClauses(params?: ListTargetingClausesParams) { + return this.client.get( + this.paramsFilterTransformer(this.resource, params), + ) + } + + /** + * Gets a list of targeting clause objects with extended fields. + * + * @param params - + * @returns + */ + @DecodeArray(SponsoredDisplayTargetingClauseExtended) + public listTargetingClausesExtended(params?: ListTargetingClausesParams) { + return this.client.get( + this.paramsFilterTransformer(`${this.resource}/extended`, params), + ) + } + + /** + * Set the status of targeting clauses to archived. + * Equivalent to using the updateTargetingClauses operation to set the state property of a targeting clause to archived. + * + * @param targetId - + * @returns + */ + @Decode(TargetingClauseResponse) + public archiveTargetingClause(targetId: TargetId) { + return this.client.delete(`${this.resource}/${targetId}`) + } +} diff --git a/src/operations/product-targeting/types.ts b/src/operations/product-targeting/types.ts index 3df1f0250..f2d29a20f 100644 --- a/src/operations/product-targeting/types.ts +++ b/src/operations/product-targeting/types.ts @@ -1081,3 +1081,154 @@ export const SponsoredBrandsBatchGetNegativeTargetsResponse = t.strict({ export type SponsoredBrandsBatchGetNegativeTargetsResponse = t.TypeOf< typeof SponsoredBrandsBatchGetNegativeTargetsResponse > + +// Sponsored Display Types + +export const SponsoredDisplayTargetingPredicateType = t.union([ + t.literal('asinSameAs'), + t.literal('asinCategorySameAs'), + t.literal('asinBrandSameAs'), + t.literal('asinPriceBetween'), + t.literal('asinPriceGreaterThan'), + t.literal('asinPriceLessThan'), + t.literal('asinReviewRatingLessThan'), + t.literal('asinReviewRatingGreaterThan'), + t.literal('asinReviewRatingBetween'), + t.literal('similarProduct'), + t.literal('exactProduct'), + t.literal('asinIsPrimeShippingEligible'), + t.literal('asinAgeRangeSameAs'), + t.literal('asinGenreSameAs'), + t.literal('lookback'), + t.literal('negative'), +]) +export type SponsoredDisplayTargetingPredicateType = t.TypeOf< + typeof SponsoredDisplayTargetingPredicateType +> + +export const SponsoredDisplayTargetingPredicate = t.strict({ + type: SponsoredDisplayTargetingPredicateType, + + /** + * The value to be targeted. + */ + value: t.string, +}) +export type SponsoredDisplayTargetingPredicate = t.TypeOf + +export const SponsoredDisplayTargetingPredicateLegacy = t.strict({ + type: SponsoredDisplayTargetingPredicateType, + + /** + * The value to be targeted. + */ + value: t.string, + + /** + * The type of event that the value applies to. Only available for similarProduct and exactProduct currently. + */ + eventType: t.literal('views'), +}) +export type SponsoredDisplayTargetingPredicateLegacy = t.TypeOf< + typeof SponsoredDisplayTargetingPredicateLegacy +> + +export const SponsoredDisplayTargetingPredicateNested = t.strict({ + type: t.literal('views'), + + value: t.array(SponsoredDisplayTargetingPredicate), +}) +export type SponsoredDisplayTargetingPredicateNested = t.TypeOf< + typeof SponsoredDisplayTargetingPredicateNested +> + +export const SponsoredDisplayTargetingExpression = t.union([ + SponsoredDisplayTargetingPredicate, + SponsoredDisplayTargetingPredicateLegacy, + SponsoredDisplayTargetingPredicateNested, +]) +export type SponsoredDisplayTargetingExpression = t.TypeOf< + typeof SponsoredDisplayTargetingExpression +> + +export const CreateSponsoredDisplayTargetingClausesParams = t.strict({ + /** + * The ID of the ad group to which this target belongs. + */ + adGroupId: AdGroupId, + + /** + * Advertiser-specified state of the target + */ + state: TargetingClauseState, + + /** + * The type of expression. + * Tactic T00020 ad groups only allow manual targeting. + */ + expressionType: ExpressionType, + + /** + * The bid will override the adGroup bid if specified. Bid is not allowed in negative targeting clauses. + */ + bid: t.number, + + /** + * The targeting expression to match against. + */ + expression: t.array(SponsoredDisplayTargetingExpression), +}) +export type CreateSponsoredDisplayTargetingClausesParams = t.TypeOf< + typeof CreateSponsoredDisplayTargetingClausesParams +> + +export const UpdateSponsoredDisplayTargetingClausesParams = t.intersection([ + t.strict({ + targetId: TargetId, + }), + t.partial({ + /** + * The bid will override the adGroup bid if specified. Bid is not allowed in negative targeting clauses. + */ + bid: t.number, + + /** + * Advertiser-specified state of the target + */ + state: TargetingClauseState, + }), +]) +export type UpdateSponsoredDisplayTargetingClausesParams = t.TypeOf< + typeof UpdateSponsoredDisplayTargetingClausesParams +> + +export const SponsoredDisplayTargetingClause = t.intersection([ + CreateSponsoredDisplayTargetingClausesParams, + t.strict({ + targetId: TargetId, + }), +]) +export type SponsoredDisplayTargetingClause = t.TypeOf + +export const SponsoredDisplayTargetingClauseExtended = t.intersection([ + SponsoredDisplayTargetingClause, + t.strict({ + /** + * The date the ad group was created as epoch time in milliseconds. + */ + creationDate: DateFromNumber, + + /** + * The date the ad group was last updated as epoch time in milliseconds. + */ + lastUpdatedDate: DateFromNumber, + + /** + * The computed status, accounting for out of budget, policy violations, etc. See developer notes for more information. + */ + servingStatus: TargetingClauseServingStatus, + }), +]) +export type SponsoredDisplayTargetingClauseExtended = t.TypeOf< + typeof SponsoredDisplayTargetingClauseExtended +> diff --git a/test/__recordings__/SponsoredDisplayAdGroupOperation_3544596599/createAdGroups_767840800/should-create-an-ad-group_2863360381/recording.har b/test/__recordings__/SponsoredDisplayAdGroupOperation_3544596599/createAdGroups_767840800/should-create-an-ad-group_2863360381/recording.har index a7fdea335..9f2f6b87c 100644 --- a/test/__recordings__/SponsoredDisplayAdGroupOperation_3544596599/createAdGroups_767840800/should-create-an-ad-group_2863360381/recording.har +++ b/test/__recordings__/SponsoredDisplayAdGroupOperation_3544596599/createAdGroups_767840800/should-create-an-ad-group_2863360381/recording.har @@ -79,13 +79,13 @@ "url": "https://advertising-api-test.amazon.com/v2/sp/adGroups" }, "response": { - "bodySize": 47, + "bodySize": 48, "content": { "mimeType": "application/json", - "size": 47, + "size": 48, "text": [ { - "adGroupId": 83691965128172, + "adGroupId": 257081908560802, "code": "SUCCESS" } ] @@ -98,7 +98,7 @@ }, { "name": "date", - "value": "Sun, 16 Aug 2020 15:31:22 GMT" + "value": "Sat, 22 Aug 2020 10:34:20 GMT" }, { "name": "content-type", @@ -114,7 +114,7 @@ }, { "name": "x-amz-request-id", - "value": "GGAFQ77G4ZTQPE1SZKX7" + "value": "R6KGFJ3BW61GJ0MS5HKX" }, { "name": "vary", @@ -127,8 +127,8 @@ "status": 207, "statusText": "Multi-Status" }, - "startedDateTime": "2020-08-16T15:31:22.703Z", - "time": 203, + "startedDateTime": "2020-08-22T10:34:20.757Z", + "time": 156, "timings": { "blocked": -1, "connect": -1, @@ -136,7 +136,7 @@ "receive": 0, "send": 0, "ssl": -1, - "wait": 203 + "wait": 156 } } ], diff --git a/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-exactProduct-type_1301488206/recording.har b/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-exactProduct-type_1301488206/recording.har new file mode 100644 index 000000000..96d8b7a17 --- /dev/null +++ b/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-exactProduct-type_1301488206/recording.har @@ -0,0 +1,147 @@ +{ + "log": { + "_recordingName": "SponsoredDisplayTargetingOperation/createTargetingClauses/should create one or more targeting expressions with exactProduct type", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "5.0.0" + }, + "entries": [ + { + "_id": "60844d68ce6439736438cde6281cc7eb", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 144, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "accept", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "@scaleleap/amazon-advertising-api-sdk/0.0.0" + }, + { + "_fromType": "array", + "name": "amazon-advertising-api-scope", + "value": "2973802954634317" + }, + { + "_fromType": "array", + "name": "bidding_controls_on", + "value": "true" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "144" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "advertising-api-test.amazon.com" + } + ], + "headersSize": 955, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": [ + { + "adGroupId": 257081908560802, + "bid": 10, + "expression": [ + { + "type": "exactProduct", + "value": "B07663Z46Z" + } + ], + "expressionType": "manual", + "state": "enabled" + } + ] + }, + "queryString": [], + "url": "https://advertising-api-test.amazon.com/v2/sd/targets" + }, + "response": { + "bodySize": 80, + "content": { + "mimeType": "application/json", + "size": 80, + "text": { + "code": "403", + "details": "HTTP 403 Forbidden", + "requestId": "25BEZRV4H274KR5R8AAQ" + } + }, + "cookies": [], + "headers": [ + { + "name": "server", + "value": "Server" + }, + { + "name": "date", + "value": "Sun, 23 Aug 2020 15:41:12 GMT" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "transfer-encoding", + "value": "chunked" + }, + { + "name": "connection", + "value": "close" + }, + { + "name": "vary", + "value": "Content-Type,Accept-Encoding,X-Amzn-CDN-Cache,X-Amzn-AX-Treatment,User-Agent" + } + ], + "headersSize": 251, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 403, + "statusText": "Forbidden" + }, + "startedDateTime": "2020-08-23T15:41:12.763Z", + "time": 45, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 45 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-lookback-type_2142683412/recording.har b/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-lookback-type_2142683412/recording.har new file mode 100644 index 000000000..b5c641783 --- /dev/null +++ b/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-lookback-type_2142683412/recording.har @@ -0,0 +1,147 @@ +{ + "log": { + "_recordingName": "SponsoredDisplayTargetingOperation/createTargetingClauses/should create one or more targeting expressions with lookback type", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "5.0.0" + }, + "entries": [ + { + "_id": "60844d68ce6439736438cde6281cc7eb", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 140, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "accept", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "@scaleleap/amazon-advertising-api-sdk/0.0.0" + }, + { + "_fromType": "array", + "name": "amazon-advertising-api-scope", + "value": "2973802954634317" + }, + { + "_fromType": "array", + "name": "bidding_controls_on", + "value": "true" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "140" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "advertising-api-test.amazon.com" + } + ], + "headersSize": 955, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": [ + { + "adGroupId": 257081908560802, + "bid": 10, + "expression": [ + { + "type": "lookback", + "value": "B07663Z46Z" + } + ], + "expressionType": "manual", + "state": "enabled" + } + ] + }, + "queryString": [], + "url": "https://advertising-api-test.amazon.com/v2/sd/targets" + }, + "response": { + "bodySize": 80, + "content": { + "mimeType": "application/json", + "size": 80, + "text": { + "code": "403", + "details": "HTTP 403 Forbidden", + "requestId": "KT5AKPH31JBTD15X19TX" + } + }, + "cookies": [], + "headers": [ + { + "name": "server", + "value": "Server" + }, + { + "name": "date", + "value": "Sun, 23 Aug 2020 15:41:12 GMT" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "transfer-encoding", + "value": "chunked" + }, + { + "name": "connection", + "value": "close" + }, + { + "name": "vary", + "value": "Content-Type,Accept-Encoding,X-Amzn-CDN-Cache,X-Amzn-AX-Treatment,User-Agent" + } + ], + "headersSize": 251, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 403, + "statusText": "Forbidden" + }, + "startedDateTime": "2020-08-23T15:41:12.815Z", + "time": 44, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 44 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-negative-type_3269812077/recording.har b/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-negative-type_3269812077/recording.har new file mode 100644 index 000000000..9b6c286d3 --- /dev/null +++ b/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-negative-type_3269812077/recording.har @@ -0,0 +1,147 @@ +{ + "log": { + "_recordingName": "SponsoredDisplayTargetingOperation/createTargetingClauses/should create one or more targeting expressions with negative type", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "5.0.0" + }, + "entries": [ + { + "_id": "60844d68ce6439736438cde6281cc7eb", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 140, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "accept", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "@scaleleap/amazon-advertising-api-sdk/0.0.0" + }, + { + "_fromType": "array", + "name": "amazon-advertising-api-scope", + "value": "2973802954634317" + }, + { + "_fromType": "array", + "name": "bidding_controls_on", + "value": "true" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "140" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "advertising-api-test.amazon.com" + } + ], + "headersSize": 955, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": [ + { + "adGroupId": 257081908560802, + "bid": 10, + "expression": [ + { + "type": "negative", + "value": "B07663Z46Z" + } + ], + "expressionType": "manual", + "state": "enabled" + } + ] + }, + "queryString": [], + "url": "https://advertising-api-test.amazon.com/v2/sd/targets" + }, + "response": { + "bodySize": 80, + "content": { + "mimeType": "application/json", + "size": 80, + "text": { + "code": "403", + "details": "HTTP 403 Forbidden", + "requestId": "FSDXHPQ06CWFYTQX36WV" + } + }, + "cookies": [], + "headers": [ + { + "name": "server", + "value": "Server" + }, + { + "name": "date", + "value": "Sun, 23 Aug 2020 15:41:12 GMT" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "transfer-encoding", + "value": "chunked" + }, + { + "name": "connection", + "value": "close" + }, + { + "name": "vary", + "value": "Content-Type,Accept-Encoding,X-Amzn-CDN-Cache,X-Amzn-AX-Treatment,User-Agent" + } + ], + "headersSize": 251, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 403, + "statusText": "Forbidden" + }, + "startedDateTime": "2020-08-23T15:41:12.865Z", + "time": 35, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 35 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-similarProduct-type_1987201904/recording.har b/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-similarProduct-type_1987201904/recording.har new file mode 100644 index 000000000..5eaced389 --- /dev/null +++ b/test/__recordings__/SponsoredDisplayTargetingOperation_1019933930/createTargetingClauses_290560290/should-create-one-or-more-targeting-expressions-with-similarProduct-type_1987201904/recording.har @@ -0,0 +1,147 @@ +{ + "log": { + "_recordingName": "SponsoredDisplayTargetingOperation/createTargetingClauses/should create one or more targeting expressions with similarProduct type", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "5.0.0" + }, + "entries": [ + { + "_id": "60844d68ce6439736438cde6281cc7eb", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 141, + "cookies": [], + "headers": [ + { + "_fromType": "array", + "name": "content-type", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "accept", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "user-agent", + "value": "@scaleleap/amazon-advertising-api-sdk/0.0.0" + }, + { + "_fromType": "array", + "name": "amazon-advertising-api-scope", + "value": "2973802954634317" + }, + { + "_fromType": "array", + "name": "bidding_controls_on", + "value": "true" + }, + { + "_fromType": "array", + "name": "accept-encoding", + "value": "application/json" + }, + { + "_fromType": "array", + "name": "content-length", + "value": "141" + }, + { + "_fromType": "array", + "name": "connection", + "value": "close" + }, + { + "name": "host", + "value": "advertising-api-test.amazon.com" + } + ], + "headersSize": 955, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/json", + "params": [], + "text": [ + { + "adGroupId": 257081908560802, + "bid": 10, + "expression": [ + { + "type": "asinSameAs", + "value": "B07663Z46Z" + } + ], + "expressionType": "manual", + "state": "paused" + } + ] + }, + "queryString": [], + "url": "https://advertising-api-test.amazon.com/v2/sd/targets" + }, + "response": { + "bodySize": 80, + "content": { + "mimeType": "application/json", + "size": 80, + "text": { + "code": "403", + "details": "HTTP 403 Forbidden", + "requestId": "ZWK74DJDW8958F4RJQWW" + } + }, + "cookies": [], + "headers": [ + { + "name": "server", + "value": "Server" + }, + { + "name": "date", + "value": "Sun, 23 Aug 2020 15:41:12 GMT" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "transfer-encoding", + "value": "chunked" + }, + { + "name": "connection", + "value": "close" + }, + { + "name": "vary", + "value": "Content-Type,Accept-Encoding,X-Amzn-CDN-Cache,X-Amzn-AX-Treatment,User-Agent" + } + ], + "headersSize": 251, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 403, + "statusText": "Forbidden" + }, + "startedDateTime": "2020-08-23T15:41:12.579Z", + "time": 161, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 161 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/test/operations/product-targeting/sponsored-display-targeting-operation.test.ts b/test/operations/product-targeting/sponsored-display-targeting-operation.test.ts new file mode 100644 index 000000000..1c0b12302 --- /dev/null +++ b/test/operations/product-targeting/sponsored-display-targeting-operation.test.ts @@ -0,0 +1,98 @@ +import { SANDBOX_URI, auth } from '../../http-client-factory' +import { OperationProvider, HttpClient } from '../../../src' +import { SponsoredDisplayTargetingOperation } from '../../../src/operations/product-targeting/sponsored-display-targeting-operation' +import { CreateSponsoredDisplayTargetingClausesParams } from '../../../src/operations/product-targeting/types' + +describe('SponsoredDisplayTargetingOperation', () => { + const client = new HttpClient(SANDBOX_URI, { ...auth, scope: 2973802954634317 }, true) + const operationProvider = new OperationProvider(client) + const operation = operationProvider.create(SponsoredDisplayTargetingOperation) + const AD_GROUP_ID = 257081908560802 + const ASINS = ['B07663Z46Z', 'B07H8QMZWV', 'B07C65XFBB'] + + /** + * Sandbox API returns "HTTP 403 Forbidden" error when request. + * TODO: Need check again on Production API. + */ + describe('createTargetingClauses', () => { + it(`should create one or more targeting expressions with similarProduct type`, async () => { + const params: CreateSponsoredDisplayTargetingClausesParams[] = [ + { + adGroupId: AD_GROUP_ID, + state: 'paused', + expressionType: 'manual', + expression: [ + { + type: 'asinSameAs', + value: ASINS[0], + }, + ], + bid: 10, + }, + ] + const [res] = await operation.createTargetingClauses(params) + + expect(res.code).toBe('SUCCESS') + }) + + it(`should create one or more targeting expressions with exactProduct type`, async () => { + const params: CreateSponsoredDisplayTargetingClausesParams[] = [ + { + adGroupId: AD_GROUP_ID, + state: 'enabled', + expressionType: 'manual', + expression: [ + { + type: 'exactProduct', + value: ASINS[0], + }, + ], + bid: 10, + }, + ] + const [res] = await operation.createTargetingClauses(params) + + expect(res.code).toBe('SUCCESS') + }) + + it(`should create one or more targeting expressions with lookback type`, async () => { + const params: CreateSponsoredDisplayTargetingClausesParams[] = [ + { + adGroupId: AD_GROUP_ID, + state: 'enabled', + expressionType: 'manual', + expression: [ + { + type: 'lookback', + value: ASINS[0], + }, + ], + bid: 10, + }, + ] + const [res] = await operation.createTargetingClauses(params) + + expect(res.code).toBe('SUCCESS') + }) + + it(`should create one or more targeting expressions with negative type`, async () => { + const params: CreateSponsoredDisplayTargetingClausesParams[] = [ + { + adGroupId: AD_GROUP_ID, + state: 'enabled', + expressionType: 'manual', + expression: [ + { + type: 'negative', + value: ASINS[0], + }, + ], + bid: 10, + }, + ] + const [res] = await operation.createTargetingClauses(params) + + expect(res.code).toBe('SUCCESS') + }) + }) +})