From bb21cc5f67ff132dd299cc13f8c11f9381bebcdb Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Wed, 10 Sep 2025 14:17:41 +0200 Subject: [PATCH 01/14] feat: add support for feed recommendation --- packages/client/package.json | 4 +- ...feedRecommendationInitializationBuilder.ts | 110 ++++++++++++++ .../feedRecommendationNextItemsBuilder.ts | 19 +++ .../src/builders/recommendation/feed/index.ts | 2 + .../src/builders/recommendation/index.ts | 3 +- packages/client/src/models/data-contracts.ts | 143 ++++++++++++++++++ packages/client/src/recommender.ts | 13 +- packages/client/src/tracker.ts | 91 +++++++++-- 8 files changed, 365 insertions(+), 20 deletions(-) create mode 100644 packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts create mode 100644 packages/client/src/builders/recommendation/feed/feedRecommendationNextItemsBuilder.ts create mode 100644 packages/client/src/builders/recommendation/feed/index.ts diff --git a/packages/client/package.json b/packages/client/package.json index b5b5bc04..d5d546ed 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@relewise/client", - "version": "2.15.0", + "version": "2.21.0", "description": "Relewise is a next generation personalization SaaS-platform, which offers functionality within product- and content recommendations and personalized search. This official SDK helps you interact with our API.", "repository": { "type": "git", @@ -32,7 +32,7 @@ "prebuild:types": "rimraf ./build", "build:types": "tsc -p ./tsconfig.json --outDir build --declaration true && api-extractor run", "clean": "rimraf ./build ./dist ./docs", - "gen-api": "swagger-typescript-api -p https://api.relewise.com/public/swagger.json -o src/models --modular --no-client --enum-names-as-values && node fix-exports.js", + "gen-api": "swagger-typescript-api -p https://sandbox-api.relewise.com/3ef4dc87-6260-43c0-95e9-9b8bd9a6fe7c/public/swagger.json -o src/models --modular --no-client --enum-names-as-values && node fix-exports.js", "gen-api-dev": "swagger-typescript-api -p swagger.json -o src/models --modular --no-client --enum-names-as-values && node fix-exports.js", "publish": "npm run gen-api && npm run build && npm run build:types" }, diff --git a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts new file mode 100644 index 00000000..c68d878e --- /dev/null +++ b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts @@ -0,0 +1,110 @@ +import { Settings } from '../../../builders/settings'; +import { Feed, FeedComposition, FeedRecommendationInitializationRequest, FeedSeed, SelectedContentPropertiesSettings, SelectedProductPropertiesSettings, SelectedVariantPropertiesSettings } from '../../../models/data-contracts'; +import { RecommendationRequestBuilder } from '../recommendationRequestBuilder'; + +export class FeedRecommendationInitializationBuilder extends RecommendationRequestBuilder { + private feed: Feed; + + constructor({ minimumPageSize }: { minimumPageSize: number }, + settings: Settings) { + super(settings); + + this.feed = { + minimumPageSize: minimumPageSize, + compositions: [], + allowProductsCurrentlyInCart: false, + recommendVariant: false + }; + } + + /** + * Useful, for example, when you want to show a feed based on specific product(s) or content, such as a PDP/CDP, a shopping cart, or an order. + * @param seed + */ + public seed(seed: FeedSeed): this { + this.feed.seed = seed; + + return this; + } + + /** + * Defines how the feed will be composed, which types of entities to include, how many of each type, and any filters or relevance modifiers that should apply to each type, etc. + * @param compositions + */ + public compositions(compositions: FeedComposition[]): this { + this.feed.compositions = compositions; + + return this; + } + + /** + * Select the properties of the product to be returned, by default only the product id is returned. + * @param productProperties + */ + public setSelectedProductProperties(productProperties: Partial | null): this { + this.feed.selectedProductProperties = productProperties as SelectedProductPropertiesSettings | null; + + return this; + } + + /** + * Select the properties of the variant to be returned, by default only the variant id is returned. + * @param variantProperties + */ + public setSelectedVariantProperties(variantProperties: Partial | null): this { + this.feed.selectedVariantProperties = variantProperties as SelectedVariantPropertiesSettings | null; + + return this; + } + + /** + * Select the properties of the content to be returned, by default only the content id is returned. + * @param contentProperties + */ + public setSelectedContentProperties(contentProperties: Partial | null): this { + this.feed.selectedContentProperties = contentProperties as SelectedContentPropertiesSettings | null; + + return this; + } + + /** + * Defines if variants should be included for returned products + * @param recommend + */ + public recommendVariant(recommend: boolean = true): this { + this.feed.recommendVariant = recommend; + + return this; + } + + /** + * The minimum number of items to return initially and per every FeedRecommendationNextItemsRequest. + * A higher number of results may be returned if composition configurations dictate so. + * @param size + */ + public minimumPageSize(size: number): this { + this.feed.minimumPageSize = size; + + return this; + } + + /** + * Defines if products should be excluded if they are currently present in the users Cart + * @param allow + */ + public allowProductsCurrentlyInCart(allow: boolean = true): this { + this.feed.allowProductsCurrentlyInCart = allow; + + return this; + } + + public build() { + const request: FeedRecommendationInitializationRequest = { + $type: 'Relewise.Client.Requests.Recommendations.Feed.FeedRecommendationInitializationRequest, Relewise.Client', + ...this.baseBuild(), + feed: this.feed, + }; + + return request; + } +} diff --git a/packages/client/src/builders/recommendation/feed/feedRecommendationNextItemsBuilder.ts b/packages/client/src/builders/recommendation/feed/feedRecommendationNextItemsBuilder.ts new file mode 100644 index 00000000..831ba7f4 --- /dev/null +++ b/packages/client/src/builders/recommendation/feed/feedRecommendationNextItemsBuilder.ts @@ -0,0 +1,19 @@ +import { FeedRecommendationNextItemsRequest } from '../../../models/data-contracts'; + +export class FeedRecommendationNextItemsBuilder { + private initializedFeedId: string; + + constructor({ initializedFeedId }: { initializedFeedId: string }) { + + this.initializedFeedId = initializedFeedId; + } + + public build() { + const request: FeedRecommendationNextItemsRequest = { + $type: 'Relewise.Client.Requests.Recommendations.Feed.FeedRecommendationNextItemsRequest, Relewise.Client', + initializedFeedId: this.initializedFeedId, + }; + + return request; + } +} diff --git a/packages/client/src/builders/recommendation/feed/index.ts b/packages/client/src/builders/recommendation/feed/index.ts new file mode 100644 index 00000000..fdcc82b0 --- /dev/null +++ b/packages/client/src/builders/recommendation/feed/index.ts @@ -0,0 +1,2 @@ +export * from './feedRecommendationInitializationBuilder'; +export * from './feedRecommendationNextItemsBuilder'; \ No newline at end of file diff --git a/packages/client/src/builders/recommendation/index.ts b/packages/client/src/builders/recommendation/index.ts index d20f3adb..12f6ae4a 100644 --- a/packages/client/src/builders/recommendation/index.ts +++ b/packages/client/src/builders/recommendation/index.ts @@ -4,4 +4,5 @@ export * from './brands'; export * from './product-categories'; export * from './products'; export * from './recommendationRequestBuilder'; -export * from './search-terms'; \ No newline at end of file +export * from './search-terms'; +export * from './feed'; \ No newline at end of file diff --git a/packages/client/src/models/data-contracts.ts b/packages/client/src/models/data-contracts.ts index fcc2f19f..db3fa127 100644 --- a/packages/client/src/models/data-contracts.ts +++ b/packages/client/src/models/data-contracts.ts @@ -13,8 +13,13 @@ export type UtilRequiredKeys = Omit & Required; @@ -283,6 +288,10 @@ export type BatchedTrackingRequest = TrackingRequest & { | ProductView | SearchTerm | UserUpdate + | FeedDwell + | FeedItemClick + | FeedItemFeedback + | FeedItemPreview )[] | null; }; @@ -735,6 +744,12 @@ export interface CartDetails { data?: Record; } +export interface CartDetailsSelectedPropertiesSettings { + allData: boolean; + dataKeys?: string[] | null; + lineItems?: LineItemSelectedPropertiesSettings | null; +} + export interface Category { $type: string; id?: string | null; @@ -2134,6 +2149,92 @@ export interface FacetSorting { $type: string; } +export interface Feed { + /** @format int32 */ + minimumPageSize: number; + seed?: FeedSeed | null; + compositions: FeedComposition[]; + selectedProductProperties?: SelectedProductPropertiesSettings | null; + selectedVariantProperties?: SelectedVariantPropertiesSettings | null; + selectedContentProperties?: SelectedContentPropertiesSettings | null; + recommendVariant?: boolean | null; + allowProductsCurrentlyInCart?: boolean | null; +} + +export interface FeedComposition { + type: "Product" | "Content"; + count: Int32Range; + filters?: FilterCollection | null; + relevanceModifiers?: RelevanceModifierCollection | null; + fill?: FeedComposition | null; + name?: string | null; + includeEmptyResults: boolean; + /** @format int32 */ + rotationLimit?: number | null; +} + +export interface FeedCompositionResult { + name?: string | null; + products?: ProductResult[] | null; + content?: ContentResult[] | null; +} + +export type FeedDwell = Trackable & { + user: User; + /** @format uuid */ + feedId: string; + /** @format int32 */ + dwellTimeMilliseconds: number; + visibleItems: FeedItem[]; +}; + +export interface FeedItem { + productAndVariantId?: ProductAndVariantId | null; + contentId?: string | null; +} + +export type FeedItemClick = Trackable & { + user?: User | null; + /** @format uuid */ + feedId: string; + item?: FeedItem | null; +}; + +export type FeedItemFeedback = Trackable & { + user: User; + /** @format uuid */ + feedId: string; + item: FeedItem; + kind: "Like" | "Dislike" | "Favorite" | "Unfavorite"; +}; + +export type FeedItemPreview = Trackable & { + user?: User | null; + /** @format uuid */ + feedId: string; + item?: FeedItem | null; +}; + +export type FeedRecommendationInitializationRequest = RecommendationRequest & { + feed: Feed; +}; + +export type FeedRecommendationNextItemsRequest = LicensedRequest & { + /** @format uuid */ + initializedFeedId: string; +}; + +export type FeedRecommendationResponse = RecommendationResponse & { + /** @format uuid */ + initializedFeedId: string; + recommendations?: FeedCompositionResult[] | null; +}; + +export interface FeedSeed { + productAndVariantIds?: ProductAndVariantId[] | null; + contentIds?: string[] | null; +} + export interface FieldIndexConfiguration { included: boolean; /** @format int32 */ @@ -2326,6 +2427,12 @@ export type HasClassificationCondition = UserCondition & { value?: string | null; }; +export type HasCompanyDataCondition = UserCondition & { + key: string; + conditions?: ValueConditionCollection | null; + evaluationScope: "ImmediateCompany" | "ParentCompany" | "ImmediateOrParentCompany"; +}; + export type HasDataCondition = UserCondition & { key?: string | null; conditions?: ValueConditionCollection | null; @@ -2595,6 +2702,13 @@ export interface LineItem { data?: Record; } +export interface LineItemSelectedPropertiesSettings { + product?: SelectedProductPropertiesSettings | null; + variant?: SelectedVariantPropertiesSettings | null; + allData: boolean; + dataKeys?: string[] | null; +} + export type Location = LocationEntityStateLocationMetadataValuesRetailMediaEntity & { name: string; key?: string | null; @@ -2767,6 +2881,7 @@ export type MixedRecommendationResponseCollection = TimedResponse & { | BrandRecommendationResponse | ContentCategoryRecommendationResponse | ContentRecommendationResponse + | FeedRecommendationResponse | ProductCategoryRecommendationResponse | ProductRecommendationResponse | SearchTermRecommendationResponse @@ -4687,6 +4802,7 @@ export interface RequestContextFilter { languages?: Language[] | null; currencies?: Currency[] | null; filters?: RequestFilterCriteria | null; + searchTermCondition?: SearchTermCondition | RetailMediaSearchTermCondition | null; } export interface RequestFilterCriteria { @@ -5598,6 +5714,22 @@ export type TrackContentViewRequest = TrackingRequest & { contentView: ContentView; }; +export type TrackFeedDwellRequest = TrackingRequest & { + dwell: FeedDwell; +}; + +export type TrackFeedItemClickRequest = TrackingRequest & { + click: FeedItemClick; +}; + +export type TrackFeedItemFeedbackRequest = TrackingRequest & { + feedback: FeedItemFeedback; +}; + +export type TrackFeedItemPreviewRequest = TrackingRequest & { + preview: FeedItemPreview; +}; + export type TrackOrderRequest = TrackingRequest & { order: Order; }; @@ -5756,6 +5888,7 @@ export interface UserConditionCollection { | HasActivityCondition | HasAuthenticatedIdCondition | HasClassificationCondition + | HasCompanyDataCondition | HasDataCondition | HasEmailCondition | HasIdentifierCondition @@ -5827,6 +5960,16 @@ export interface UserResultDetails { company?: UserAssociatedCompanyResultDetails | null; } +export interface UserResultDetailsSelectedPropertiesSettings { + allClassifications: boolean; + classificationKeys?: string[] | null; + carts?: CartDetailsSelectedPropertiesSettings | null; + allIdentifiers: boolean; + identifierKeys?: string[] | null; + allData: boolean; + dataKeys?: string[] | null; +} + export type UserUpdate = Trackable & { user?: User | null; kind: "None" | "UpdateAndAppend" | "ReplaceProvidedProperties" | "ClearAndReplace"; diff --git a/packages/client/src/recommender.ts b/packages/client/src/recommender.ts index d9c01d80..0ede41e5 100644 --- a/packages/client/src/recommender.ts +++ b/packages/client/src/recommender.ts @@ -39,6 +39,9 @@ import { ProductsViewedAfterViewingContentRequest, PopularProductsRequest, PersonalProductRecommendationRequest, + FeedRecommendationInitializationRequest, + FeedRecommendationResponse, + FeedRecommendationNextItemsRequest, } from './models/data-contracts'; export class Recommender extends RelewiseClient { @@ -161,7 +164,16 @@ export class Recommender extends RelewiseClient { public async recommendContentsViewedAfterViewingContent(request: ContentsViewedAfterViewingContentRequest, options?: RelewiseRequestOptions): Promise { return this.request('ContentsViewedAfterViewingContentRequest', request, options); } + //#endregion + + //#region feed + public async recommendFeedRecommendationInitialization(request: FeedRecommendationInitializationRequest, options?: RelewiseRequestOptions): Promise { + return this.request('FeedRecommendationInitializationRequest', request, options); + } + public async recommendFeedRecommendationNextItems(request: FeedRecommendationNextItemsRequest, options?: RelewiseRequestOptions): Promise { + return this.request('FeedRecommendationNextItemsRequest', request, options); + } //#endregion //#region Batching @@ -180,6 +192,5 @@ export class Recommender extends RelewiseClient { public async batchProductCategoryRecommendations(request: ProductCategoryRecommendationRequestCollection, options?: RelewiseRequestOptions): Promise { return this.request('ProductCategoryRecommendationRequestCollection', request, options); } - //#endregion } \ No newline at end of file diff --git a/packages/client/src/tracker.ts b/packages/client/src/tracker.ts index 9b68245e..37fe349e 100644 --- a/packages/client/src/tracker.ts +++ b/packages/client/src/tracker.ts @@ -1,7 +1,16 @@ import { RelewiseClient, RelewiseClientOptions, RelewiseRequestOptions } from './relewise.client'; -import { +import { TrackOrderRequest, TrackCartRequest, TrackProductViewRequest, TrackProductCategoryViewRequest, TrackContentViewRequest, TrackContentCategoryViewRequest, TrackBrandViewRequest, User, TrackSearchTermRequest, TrackUserUpdateRequest, DataValue, + FeedDwell, + TrackFeedDwellRequest, + TrackFeedItemClickRequest, + FeedItemClick, + TrackFeedItemPreviewRequest, + FeedItemPreview, + TrackFeedItemFeedbackRequest, + FeedItemFeedback, + FeedItem, } from './models/data-contracts'; export class Tracker extends RelewiseClient { @@ -15,8 +24,8 @@ export class Tracker extends RelewiseClient { orderNumber: string, /** @deprecated Use orderNumber instead. */ trackingNumber?: string, - lineItems: { productId: string, variantId?: string, lineTotal: number, quantity: number, data?: Record }[], - data?: Record, + lineItems: { productId: string, variantId?: string, lineTotal: number, quantity: number, data?: Record }[], + data?: Record, cartName?: string }, options?: RelewiseRequestOptions): Promise { return this.request('TrackOrderRequest', { @@ -27,12 +36,12 @@ export class Tracker extends RelewiseClient { product: { id: l.productId, }, - ...(l.variantId && { variant: { id: l.variantId }}), + ...(l.variantId && { variant: { id: l.variantId } }), lineTotal: l.lineTotal, quantity: l.quantity, data: l.data, })), - subtotal: { amount: subtotal.amount, currency: { value: subtotal.currency }}, + subtotal: { amount: subtotal.amount, currency: { value: subtotal.currency } }, orderNumber: orderNumber, trackingNumber: trackingNumber, cartName: cartName, @@ -42,12 +51,12 @@ export class Tracker extends RelewiseClient { }, options); } - public async trackCart({ user, subtotal, lineItems, data, cartName = 'default' }: { - user?: User, - subtotal: { currency: string, amount: number }, - lineItems: { productId: string, variantId?: string, lineTotal: number, quantity: number, data?: Record }[], - data?: Record, - cartName?: string + public async trackCart({ user, subtotal, lineItems, data, cartName = 'default' }: { + user?: User, + subtotal: { currency: string, amount: number }, + lineItems: { productId: string, variantId?: string, lineTotal: number, quantity: number, data?: Record }[], + data?: Record, + cartName?: string }, options?: RelewiseRequestOptions): Promise { return this.request('TrackCartRequest', { $type: 'Relewise.Client.Requests.Tracking.TrackCartRequest, Relewise.Client', @@ -57,12 +66,12 @@ export class Tracker extends RelewiseClient { product: { id: l.productId, }, - ...(l.variantId && { variant: { id: l.variantId }}), + ...(l.variantId && { variant: { id: l.variantId } }), lineTotal: l.lineTotal, quantity: l.quantity, data: l.data, })), - subtotal: { amount: subtotal.amount, currency: { value: subtotal.currency }}, + subtotal: { amount: subtotal.amount, currency: { value: subtotal.currency } }, name: cartName, user: user, data: data, @@ -78,7 +87,7 @@ export class Tracker extends RelewiseClient { product: { id: productId, }, - ...(variantId && { variant: { id: variantId }}), + ...(variantId && { variant: { id: variantId } }), user: user, }, }, options); @@ -146,7 +155,7 @@ export class Tracker extends RelewiseClient { }, options); } - public async trackUserUpdate({ user, updateKind = 'UpdateAndAppend' }: { user: User, updateKind?: 'None' | 'UpdateAndAppend' | 'ReplaceProvidedProperties' | 'ClearAndReplace' }, options?: RelewiseRequestOptions): Promise { + public async trackUserUpdate({ user, updateKind = 'UpdateAndAppend' }: { user: User, updateKind?: 'None' | 'UpdateAndAppend' | 'ReplaceProvidedProperties' | 'ClearAndReplace' }, options?: RelewiseRequestOptions): Promise { return this.request('TrackUserUpdateRequest', { $type: 'Relewise.Client.Requests.Tracking.TrackUserUpdateRequest, Relewise.Client', userUpdate: { @@ -156,4 +165,54 @@ export class Tracker extends RelewiseClient { }, }, options); } -} + + public async trackFeedDwell({ user, feedId, dwellTimeMilliseconds, visibleItems }: Omit, options?: RelewiseRequestOptions) { + return this.request('TrackFeedDwellRequest', { + $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedDwellRequest, Relewise.Client', + dwell: { + $type: 'Relewise.Client.DataTypes.Feed.FeedDwell, Relewise.Client', + user: user, + feedId: feedId, + dwellTimeMilliseconds: dwellTimeMilliseconds, + visibleItems: visibleItems, + } + }, options); + } + + public async trackFeedItemClick({ user, feedId, item }: { user?: User | null; feedId: string; item?: FeedItem }, options?: RelewiseRequestOptions) { + return this.request('TrackFeedItemClickRequest', { + $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedItemClickRequest, Relewise.Client', + click: { + $type: 'Relewise.Client.DataTypes.Feed.FeedItemClick, Relewise.Client', + user: user, + feedId: feedId, + item: item, + } + }, options); + } + + public async trackFeedItemFeedback({ user, feedId, item, kind }: Omit, options?: RelewiseRequestOptions) { + return this.request('TrackFeedItemClickRequest', { + $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedItemClickRequest, Relewise.Client', + feedback: { + $type: 'Relewise.Client.DataTypes.Feed.FeedItemFeedback, Relewise.Client', + user: user, + feedId: feedId, + item: item, + kind: kind + } + }, options); + } + + public async trackFeedItemPreview({ user, feedId, item }: { user?: User | null; feedId: string; item?: FeedItem }, options?: RelewiseRequestOptions) { + return this.request('TrackFeedItemPreviewRequest', { + $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedItemPreviewRequest, Relewise.Client', + preview: { + $type: 'Relewise.Client.DataTypes.Feed.FeedItemPreview, Relewise.Client', + user: user, + feedId: feedId, + item: item, + } + }, options); + } +} \ No newline at end of file From 8f0f4fe1c24b41503bd285cf4eaf75f2d84603a5 Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Thu, 11 Sep 2025 08:26:02 +0200 Subject: [PATCH 02/14] self review --- packages/client/package.json | 2 +- .../recommendation/feed/feedRecommendationNextItemsBuilder.ts | 1 - packages/client/src/tracker.ts | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/client/package.json b/packages/client/package.json index d5d546ed..08f4422a 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@relewise/client", - "version": "2.21.0", + "version": "2.22.0", "description": "Relewise is a next generation personalization SaaS-platform, which offers functionality within product- and content recommendations and personalized search. This official SDK helps you interact with our API.", "repository": { "type": "git", diff --git a/packages/client/src/builders/recommendation/feed/feedRecommendationNextItemsBuilder.ts b/packages/client/src/builders/recommendation/feed/feedRecommendationNextItemsBuilder.ts index 831ba7f4..c188ff8e 100644 --- a/packages/client/src/builders/recommendation/feed/feedRecommendationNextItemsBuilder.ts +++ b/packages/client/src/builders/recommendation/feed/feedRecommendationNextItemsBuilder.ts @@ -4,7 +4,6 @@ export class FeedRecommendationNextItemsBuilder { private initializedFeedId: string; constructor({ initializedFeedId }: { initializedFeedId: string }) { - this.initializedFeedId = initializedFeedId; } diff --git a/packages/client/src/tracker.ts b/packages/client/src/tracker.ts index 37fe349e..f8302226 100644 --- a/packages/client/src/tracker.ts +++ b/packages/client/src/tracker.ts @@ -192,8 +192,8 @@ export class Tracker extends RelewiseClient { } public async trackFeedItemFeedback({ user, feedId, item, kind }: Omit, options?: RelewiseRequestOptions) { - return this.request('TrackFeedItemClickRequest', { - $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedItemClickRequest, Relewise.Client', + return this.request('TrackFeedItemFeedbackRequest', { + $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedItemFeedbackRequest, Relewise.Client', feedback: { $type: 'Relewise.Client.DataTypes.Feed.FeedItemFeedback, Relewise.Client', user: user, From fe5d6e57b7db796b965fce27d15903e1103a6fce Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Thu, 11 Sep 2025 12:21:49 +0200 Subject: [PATCH 03/14] tweaks --- .../feed/feedCompositionBuilder.ts | 57 +++++++++++++++++++ ...feedRecommendationInitializationBuilder.ts | 14 ++++- ...ContentRecommendations.integration.test.ts | 19 ++++++- 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts diff --git a/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts b/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts new file mode 100644 index 00000000..9873c1a3 --- /dev/null +++ b/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts @@ -0,0 +1,57 @@ +import { FilterBuilder } from 'src/builders/filterBuilder'; +import { FeedComposition, Int32Range } from '../../../models/data-contracts'; +import { RelevanceModifierBuilder } from 'src/builders/relevanceModifierBuilder'; + +export class FeedCompositionBuilder { + private composition: FeedComposition; + + constructor({ type, count }: { type: 'Product' | 'Content', count: Int32Range }) { + this.composition = { + includeEmptyResults: false, + type, + count, + }; + } + + public includeEmptyResults(allow: boolean = true): this { + this.composition.includeEmptyResults = allow; + + return this; + } + + public rotationLimit(limit: number): this { + this.composition.rotationLimit = limit; + + return this; + } + + public fill(options: { type: 'Product' | 'Content', count: Int32Range }, fill: (fillBuilder: FeedCompositionBuilder) => void): this { + const builder = new FeedCompositionBuilder(options); + fill(builder); + this.composition.fill = builder.build(); + + return this; + } + + public filters(filterBuilder: (builder: FilterBuilder) => void): this { + const builder = new FilterBuilder(); + filterBuilder(builder); + + this.composition.filters = builder.build(); + + return this; + } + + public relevanceModifiers(relevanceModifiersBuilder: (builder: RelevanceModifierBuilder) => void): this { + const builder = new RelevanceModifierBuilder(); + relevanceModifiersBuilder(builder); + + this.composition.relevanceModifiers = builder.build(); + + return this; + } + + public build() { + return this.composition; + } +} diff --git a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts index c68d878e..4a5bf9fc 100644 --- a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts +++ b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts @@ -1,6 +1,7 @@ import { Settings } from '../../../builders/settings'; -import { Feed, FeedComposition, FeedRecommendationInitializationRequest, FeedSeed, SelectedContentPropertiesSettings, SelectedProductPropertiesSettings, SelectedVariantPropertiesSettings } from '../../../models/data-contracts'; +import { Feed, FeedComposition, FeedRecommendationInitializationRequest, FeedSeed, Int32Range, SelectedContentPropertiesSettings, SelectedProductPropertiesSettings, SelectedVariantPropertiesSettings } from '../../../models/data-contracts'; import { RecommendationRequestBuilder } from '../recommendationRequestBuilder'; +import { FeedCompositionBuilder } from './feedCompositionBuilder'; export class FeedRecommendationInitializationBuilder extends RecommendationRequestBuilder { private feed: Feed; @@ -37,6 +38,17 @@ export class FeedRecommendationInitializationBuilder extends RecommendationReque return this; } + public addCompostion(options: { type: 'Product' | 'Content', count: Int32Range }, builderFn: (fillBuilder: FeedCompositionBuilder) => void): this { + this.feed.compositions ??= []; + + const builder = new FeedCompositionBuilder(options); + builderFn(builder); + + this.feed.compositions.push(builder.build()); + + return this; + } + /** * Select the properties of the product to be returned, by default only the product id is returned. * @param productProperties diff --git a/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts b/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts index a0cbfd09..f9faf3f7 100644 --- a/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts +++ b/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts @@ -1,4 +1,4 @@ -import { ContentRecommendationRequestCollection, ContentsRecommendationCollectionBuilder, ContentsViewedAfterViewingContentBuilder, PopularContentsBuilder, Recommender, UserFactory } from '../../src'; +import { ContentRecommendationRequestCollection, ContentsRecommendationCollectionBuilder, ContentsViewedAfterViewingContentBuilder, FeedRecommendationInitializationBuilder, PopularContentsBuilder, Recommender, UserFactory } from '../../src'; import { test, expect } from '@jest/globals' const { npm_config_API_KEY: API_KEY, npm_config_DATASET_ID: DATASET_ID, npm_config_SERVER_URL: SERVER_URL } = process.env; @@ -12,9 +12,9 @@ const settings = { user: UserFactory.anonymous(), }; -test('Batched Content Reommendations', async() => { +test('Batched Content Reommendations', async () => { - const request: ContentRecommendationRequestCollection = new ContentsRecommendationCollectionBuilder() + const request: ContentRecommendationRequestCollection = new ContentsRecommendationCollectionBuilder() .addRequest(new PopularContentsBuilder(settings).sinceMinutesAgo(5000).setNumberOfRecommendations(1).build()) .addRequest(new ContentsViewedAfterViewingContentBuilder(settings).setNumberOfRecommendations(1).setContentId('1').build()) .build(); @@ -25,4 +25,17 @@ test('Batched Content Reommendations', async() => { expect(result!.responses![0].recommendations?.length).toBeGreaterThan(0); expect(result!.responses![1].recommendations?.length).toBeGreaterThan(0); +}); + +test('Batched Content Reommendations', async () => { + + const t = new FeedRecommendationInitializationBuilder({ minimumPageSize: 10 }, settings) + .addCompostion({ + type: 'Product', + count: { lowerBoundInclusive: 1, upperBoundInclusive: 2 } + }, + b => b + .filters(f => f.addContentCategoryIdFilter('Imm', 2)) + .rotationLimit(1) + ); }); \ No newline at end of file From 8da3274d7477625a56285a9205e0c6349d0c0949 Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Thu, 18 Sep 2025 10:13:27 +0200 Subject: [PATCH 04/14] add engagement --- packages/client/package.json | 4 +- packages/client/src/models/data-contracts.ts | 261 ++++++++++-------- packages/client/src/tracker.ts | 47 ++-- .../tracker.integration.test.ts | 51 ++-- 4 files changed, 205 insertions(+), 158 deletions(-) diff --git a/packages/client/package.json b/packages/client/package.json index 08f4422a..61518b0b 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@relewise/client", - "version": "2.22.0", + "version": "2.23.0", "description": "Relewise is a next generation personalization SaaS-platform, which offers functionality within product- and content recommendations and personalized search. This official SDK helps you interact with our API.", "repository": { "type": "git", @@ -32,7 +32,7 @@ "prebuild:types": "rimraf ./build", "build:types": "tsc -p ./tsconfig.json --outDir build --declaration true && api-extractor run", "clean": "rimraf ./build ./dist ./docs", - "gen-api": "swagger-typescript-api -p https://sandbox-api.relewise.com/3ef4dc87-6260-43c0-95e9-9b8bd9a6fe7c/public/swagger.json -o src/models --modular --no-client --enum-names-as-values && node fix-exports.js", + "gen-api": "swagger-typescript-api -p https://sandbox-api.relewise.com/33126744-648a-441a-9c61-091ae00333ad/public/swagger.json -o src/models --modular --no-client --enum-names-as-values && node fix-exports.js", "gen-api-dev": "swagger-typescript-api -p swagger.json -o src/models --modular --no-client --enum-names-as-values && node fix-exports.js", "publish": "npm run gen-api && npm run build && npm run build:types" }, diff --git a/packages/client/src/models/data-contracts.ts b/packages/client/src/models/data-contracts.ts index db3fa127..061d4910 100644 --- a/packages/client/src/models/data-contracts.ts +++ b/packages/client/src/models/data-contracts.ts @@ -43,7 +43,7 @@ export interface AbandonedCartTriggerResultTriggerConfiguration { export type AbandonedSearchTriggerConfiguration = AbandonedSearchTriggerResultTriggerConfiguration & { searchTypesInPrioritizedOrder: ("Product" | "ProductCategory" | "Content")[]; - searchTermCondition?: SearchTermCondition | RetailMediaSearchTermCondition | null; + searchTermCondition?: SearchTermCondition | SearchTermConditionByLanguage | null; suppressOnEntityFromSearchResultViewed: boolean; /** @format int32 */ considerAbandonedAfterMinutes: number; @@ -70,13 +70,32 @@ export interface AbandonedSearchTriggerResultTriggerConfiguration { userConditions?: UserConditionCollection | null; } -export type Advertiser = AdvertiserEntityStateAdvertiserMetadataValuesRetailMediaEntity & { +export type Advertiser = AdvertiserEntityStateGuidNullableAdvertiserMetadataValuesRetailMediaEntity & { name: string; allowedPromotions?: PromotionSpecificationCollection | null; allowedLocations?: PromotionLocationCollection | null; }; -export interface AdvertiserAdvertiserEntityStateEntityResponse { +export interface AdvertiserEntityStateGuidNullableAdvertiserMetadataValuesAdvertisersRequestSortByAdvertisersRequestEntityFiltersEntitiesRequest { + $type: string; + filters?: AdvertisersRequestEntityFilters | null; + sorting?: AdvertisersRequestSortBySorting | null; + /** @format int32 */ + skip: number; + /** @format int32 */ + take: number; + custom?: Record; +} + +export interface AdvertiserEntityStateGuidNullableAdvertiserMetadataValuesRetailMediaEntity { + $type: string; + state: "Active" | "Inactive" | "Archived"; + metadata: AdvertiserMetadataValues; + /** @format uuid */ + id?: string | null; +} + +export interface AdvertiserGuidNullableAdvertiserEntityStateEntityResponse { $type: string; entities?: Advertiser[] | null; /** @format int32 */ @@ -92,23 +111,17 @@ export interface AdvertiserAdvertiserEntityStateEntityResponse { statistics?: Statistics | null; } -export interface AdvertiserEntityStateAdvertiserMetadataValuesAdvertisersRequestSortByAdvertisersRequestEntityFiltersEntitiesRequest { +export interface AdvertiserGuidNullableSaveEntitiesRequest { $type: string; - filters?: AdvertisersRequestEntityFilters | null; - sorting?: AdvertisersRequestSortBySorting | null; - /** @format int32 */ - skip: number; - /** @format int32 */ - take: number; + entities: Advertiser[]; + modifiedBy: string; custom?: Record; } -export interface AdvertiserEntityStateAdvertiserMetadataValuesRetailMediaEntity { +export interface AdvertiserGuidNullableSaveEntitiesResponse { $type: string; - state: "Active" | "Inactive" | "Archived"; - metadata: AdvertiserMetadataValues; - /** @format uuid */ - id?: string | null; + entities?: Advertiser[] | null; + statistics?: Statistics | null; } export type AdvertiserMetadataValues = MetadataValues & { @@ -123,24 +136,11 @@ export type AdvertiserMetadataValues = MetadataValues & { archivedBy?: string | null; }; -export interface AdvertiserSaveEntitiesRequest { - $type: string; - entities: Advertiser[]; - modifiedBy: string; - custom?: Record; -} - -export interface AdvertiserSaveEntitiesResponse { - $type: string; - entities?: Advertiser[] | null; - statistics?: Statistics | null; -} - export type AdvertisersRequest = - AdvertiserEntityStateAdvertiserMetadataValuesAdvertisersRequestSortByAdvertisersRequestEntityFiltersEntitiesRequest; + AdvertiserEntityStateGuidNullableAdvertiserMetadataValuesAdvertisersRequestSortByAdvertisersRequestEntityFiltersEntitiesRequest; export type AdvertisersRequestEntityFilters = - RetailMediaEntity2AdvertiserEntityStateAdvertiserMetadataValuesRetailMediaEntity2EntityFilters & { + RetailMediaEntity3AdvertiserEntityStateGuidNullableAdvertiserMetadataValuesRetailMediaEntity3EntityFilters & { ids?: string[] | null; }; @@ -149,7 +149,7 @@ export interface AdvertisersRequestSortBySorting { sortOrder: "Ascending" | "Descending"; } -export type AdvertisersResponse = AdvertiserAdvertiserEntityStateEntityResponse; +export type AdvertisersResponse = AdvertiserGuidNullableAdvertiserEntityStateEntityResponse; export interface AnalyzerRequest { $type: string; @@ -277,6 +277,7 @@ export type BatchedTrackingRequest = TrackingRequest & { | ContentCategoryAdministrativeAction | ContentCategoryUpdate | ContentCategoryView + | ContentEngagement | ContentUpdate | ContentView | Order @@ -284,13 +285,13 @@ export type BatchedTrackingRequest = TrackingRequest & { | ProductCategoryAdministrativeAction | ProductCategoryUpdate | ProductCategoryView + | ProductEngagement | ProductUpdate | ProductView | SearchTerm | UserUpdate | FeedDwell | FeedItemClick - | FeedItemFeedback | FeedItemPreview )[] | null; @@ -570,7 +571,7 @@ export type CPMBudget = Budget & { costPerMille: number; }; -export type Campaign = CampaignEntityStateCampaignMetadataValuesRetailMediaEntity & { +export type Campaign = CampaignEntityStateGuidNullableCampaignMetadataValuesRetailMediaEntity & { name: string; schedule?: ISchedule | null; promotions: PromotionCollection; @@ -626,10 +627,29 @@ export type CampaignAnalyticsResponse = TimedResponse & { }; export type CampaignCampaignConditions = RetailMediaConditions & { - searchTerm?: RetailMediaSearchTermConditionCollection | null; + searchTerm?: SearchTermConditionByLanguageCollection | null; }; -export interface CampaignCampaignEntityStateEntityResponse { +export interface CampaignEntityStateGuidNullableCampaignMetadataValuesCampaignsRequestSortByCampaignsRequestEntityFiltersEntitiesRequest { + $type: string; + filters?: CampaignsRequestEntityFilters | null; + sorting?: CampaignsRequestSortBySorting | null; + /** @format int32 */ + skip: number; + /** @format int32 */ + take: number; + custom?: Record; +} + +export interface CampaignEntityStateGuidNullableCampaignMetadataValuesRetailMediaEntity { + $type: string; + state: "Proposed" | "Approved" | "Archived"; + metadata: CampaignMetadataValues; + /** @format uuid */ + id?: string | null; +} + +export interface CampaignGuidNullableCampaignEntityStateEntityResponse { $type: string; entities?: Campaign[] | null; /** @format int32 */ @@ -645,23 +665,17 @@ export interface CampaignCampaignEntityStateEntityResponse { statistics?: Statistics | null; } -export interface CampaignEntityStateCampaignMetadataValuesCampaignsRequestSortByCampaignsRequestEntityFiltersEntitiesRequest { +export interface CampaignGuidNullableSaveEntitiesRequest { $type: string; - filters?: CampaignsRequestEntityFilters | null; - sorting?: CampaignsRequestSortBySorting | null; - /** @format int32 */ - skip: number; - /** @format int32 */ - take: number; + entities: Campaign[]; + modifiedBy: string; custom?: Record; } -export interface CampaignEntityStateCampaignMetadataValuesRetailMediaEntity { +export interface CampaignGuidNullableSaveEntitiesResponse { $type: string; - state: "Proposed" | "Approved" | "Archived"; - metadata: CampaignMetadataValues; - /** @format uuid */ - id?: string | null; + entities?: Campaign[] | null; + statistics?: Statistics | null; } export type CampaignMetadataValues = MetadataValues & { @@ -676,19 +690,6 @@ export type CampaignMetadataValues = MetadataValues & { archivedBy?: string | null; }; -export interface CampaignSaveEntitiesRequest { - $type: string; - entities: Campaign[]; - modifiedBy: string; - custom?: Record; -} - -export interface CampaignSaveEntitiesResponse { - $type: string; - entities?: Campaign[] | null; - statistics?: Statistics | null; -} - export interface CampaignStatusWithHistory { current: "Active" | "Inactive" | "ScheduleCompleted" | "BudgetReached"; history: CampaignStatusWithHistoryChange[]; @@ -701,10 +702,10 @@ export interface CampaignStatusWithHistoryChange { } export type CampaignsRequest = - CampaignEntityStateCampaignMetadataValuesCampaignsRequestSortByCampaignsRequestEntityFiltersEntitiesRequest; + CampaignEntityStateGuidNullableCampaignMetadataValuesCampaignsRequestSortByCampaignsRequestEntityFiltersEntitiesRequest; export type CampaignsRequestEntityFilters = - RetailMediaEntity2CampaignEntityStateCampaignMetadataValuesRetailMediaEntity2EntityFilters & { + RetailMediaEntity3CampaignEntityStateGuidNullableCampaignMetadataValuesRetailMediaEntity3EntityFilters & { ids?: string[] | null; advertiserIds?: string[] | null; }; @@ -714,7 +715,7 @@ export interface CampaignsRequestSortBySorting { sortOrder: "Ascending" | "Descending"; } -export type CampaignsResponse = CampaignCampaignEntityStateEntityResponse; +export type CampaignsResponse = CampaignGuidNullableCampaignEntityStateEntityResponse; export type Cart = Trackable & { user?: User | null; @@ -1209,6 +1210,17 @@ export type ContentDetailsCollectionResponse = TimedResponse & { export type ContentDisabledFilter = Filter; +export type ContentEngagement = Trackable & { + user?: User | null; + id: string; + engagement: ContentEngagementData; +}; + +export interface ContentEngagementData { + sentiment?: "Neutral" | "Like" | "Dislike" | null; + isFavorite?: boolean | null; +} + export type ContentFacetQuery = FacetQuery & { items: ( | ContentAssortmentFacet @@ -2200,14 +2212,6 @@ export type FeedItemClick = Trackable & { item?: FeedItem | null; }; -export type FeedItemFeedback = Trackable & { - user: User; - /** @format uuid */ - feedId: string; - item: FeedItem; - kind: "Like" | "Dislike" | "Favorite" | "Unfavorite"; -}; - export type FeedItemPreview = Trackable & { user?: User | null; /** @format uuid */ @@ -2709,14 +2713,14 @@ export interface LineItemSelectedPropertiesSettings { dataKeys?: string[] | null; } -export type Location = LocationEntityStateLocationMetadataValuesRetailMediaEntity & { +export type Location = LocationEntityStateGuidNullableLocationMetadataValuesRetailMediaEntity & { name: string; key?: string | null; placements?: LocationPlacementCollection | null; supportedPromotions?: PromotionSpecificationCollection | null; }; -export interface LocationEntityStateLocationMetadataValuesLocationsRequestSortByLocationsRequestEntityFiltersEntitiesRequest { +export interface LocationEntityStateGuidLocationMetadataValuesLocationsRequestSortByLocationsRequestEntityFiltersEntitiesRequest { $type: string; filters?: LocationsRequestEntityFilters | null; sorting?: LocationsRequestSortBySorting | null; @@ -2727,7 +2731,7 @@ export interface LocationEntityStateLocationMetadataValuesLocationsRequestSortBy custom?: Record; } -export interface LocationEntityStateLocationMetadataValuesRetailMediaEntity { +export interface LocationEntityStateGuidNullableLocationMetadataValuesRetailMediaEntity { $type: string; state: "Active" | "Inactive" | "Archived"; metadata: LocationMetadataValues; @@ -2735,7 +2739,7 @@ export interface LocationEntityStateLocationMetadataValuesRetailMediaEntity { id?: string | null; } -export interface LocationLocationEntityStateEntityResponse { +export interface LocationGuidNullableLocationEntityStateEntityResponse { $type: string; entities?: Location[] | null; /** @format int32 */ @@ -2751,6 +2755,19 @@ export interface LocationLocationEntityStateEntityResponse { statistics?: Statistics | null; } +export interface LocationGuidNullableSaveEntitiesRequest { + $type: string; + entities: Location[]; + modifiedBy: string; + custom?: Record; +} + +export interface LocationGuidNullableSaveEntitiesResponse { + $type: string; + entities?: Location[] | null; + statistics?: Statistics | null; +} + export type LocationMetadataValues = MetadataValues & { /** @format date-time */ inactivated?: string | null; @@ -2784,24 +2801,11 @@ export interface LocationPlacementVariationCollection { items: LocationPlacementVariation[]; } -export interface LocationSaveEntitiesRequest { - $type: string; - entities: Location[]; - modifiedBy: string; - custom?: Record; -} - -export interface LocationSaveEntitiesResponse { - $type: string; - entities?: Location[] | null; - statistics?: Statistics | null; -} - export type LocationsRequest = - LocationEntityStateLocationMetadataValuesLocationsRequestSortByLocationsRequestEntityFiltersEntitiesRequest; + LocationEntityStateGuidLocationMetadataValuesLocationsRequestSortByLocationsRequestEntityFiltersEntitiesRequest; export type LocationsRequestEntityFilters = - RetailMediaEntity2LocationEntityStateLocationMetadataValuesRetailMediaEntity2EntityFilters & { + RetailMediaEntity3LocationEntityStateGuidLocationMetadataValuesRetailMediaEntity3EntityFilters & { ids?: string[] | null; keys?: string[] | null; }; @@ -2811,7 +2815,7 @@ export interface LocationsRequestSortBySorting { sortOrder: "Ascending" | "Descending"; } -export type LocationsResponse = LocationLocationEntityStateEntityResponse; +export type LocationsResponse = LocationGuidNullableLocationEntityStateEntityResponse; export interface MatchTypeSettings { compound: boolean; @@ -3236,7 +3240,7 @@ export interface PredictionConfiguration { } export type PredictionRule = SearchRule & { - condition: SearchTermCondition | RetailMediaSearchTermCondition; + condition: SearchTermCondition | SearchTermConditionByLanguage; promote?: PredictionRulePromotion | null; suppress?: PredictionRuleSuppression | null; }; @@ -3841,6 +3845,17 @@ export type ProductDisplayNameFilter = Filter & { mustMatchAllConditions: boolean; }; +export type ProductEngagement = Trackable & { + user?: User | null; + id: ProductAndVariantId; + engagement: ProductEngagementData; +}; + +export interface ProductEngagementData { + sentiment?: "Neutral" | "Like" | "Dislike" | null; + isFavorite?: boolean | null; +} + export type ProductFacetQuery = FacetQuery & { items: ( | ContentAssortmentFacet @@ -4122,7 +4137,7 @@ export type ProductPromotion = Promotion & { }; export type ProductPromotionPromotionConditions = RetailMediaConditions & { - searchTerm?: RetailMediaSearchTermConditionCollection | null; + searchTerm?: SearchTermConditionByLanguageCollection | null; }; export type ProductPromotionSpecification = PromotionSpecification & { @@ -4689,13 +4704,13 @@ export interface RecommendationTypeCollection { export interface RedirectResult { /** @format uuid */ id: string; - condition: SearchTermCondition | RetailMediaSearchTermCondition; + condition: SearchTermCondition | SearchTermConditionByLanguage; destination?: string | null; data?: Record; } export type RedirectRule = SearchRule & { - condition: SearchTermCondition | RetailMediaSearchTermCondition; + condition: SearchTermCondition | SearchTermConditionByLanguage; destination?: string | null; data?: Record; }; @@ -4802,7 +4817,7 @@ export interface RequestContextFilter { languages?: Language[] | null; currencies?: Currency[] | null; filters?: RequestFilterCriteria | null; - searchTermCondition?: SearchTermCondition | RetailMediaSearchTermCondition | null; + searchTerms?: SearchTermConditionByLanguageCollection | null; } export interface RequestFilterCriteria { @@ -4819,19 +4834,19 @@ export interface RetailMediaConditions { $type: string; } -export interface RetailMediaEntity2AdvertiserEntityStateAdvertiserMetadataValuesRetailMediaEntity2EntityFilters { +export interface RetailMediaEntity3AdvertiserEntityStateGuidNullableAdvertiserMetadataValuesRetailMediaEntity3EntityFilters { $type: string; term?: string | null; states?: ("Active" | "Inactive" | "Archived")[] | null; } -export interface RetailMediaEntity2CampaignEntityStateCampaignMetadataValuesRetailMediaEntity2EntityFilters { +export interface RetailMediaEntity3CampaignEntityStateGuidNullableCampaignMetadataValuesRetailMediaEntity3EntityFilters { $type: string; term?: string | null; states?: ("Proposed" | "Approved" | "Archived")[] | null; } -export interface RetailMediaEntity2LocationEntityStateLocationMetadataValuesRetailMediaEntity2EntityFilters { +export interface RetailMediaEntity3LocationEntityStateGuidLocationMetadataValuesRetailMediaEntity3EntityFilters { $type: string; term?: string | null; states?: ("Active" | "Inactive" | "Archived")[] | null; @@ -4871,21 +4886,13 @@ export interface RetailMediaResultPlacementResultEntityProduct { result: ProductResult; } -export type RetailMediaSearchTermCondition = SearchTermCondition & { - language?: Language | null; -}; - -export interface RetailMediaSearchTermConditionCollection { - values?: RetailMediaSearchTermCondition[] | null; -} +export type SaveAdvertisersRequest = AdvertiserGuidNullableSaveEntitiesRequest; -export type SaveAdvertisersRequest = AdvertiserSaveEntitiesRequest; +export type SaveAdvertisersResponse = AdvertiserGuidNullableSaveEntitiesResponse; -export type SaveAdvertisersResponse = AdvertiserSaveEntitiesResponse; +export type SaveCampaignsRequest = CampaignGuidNullableSaveEntitiesRequest; -export type SaveCampaignsRequest = CampaignSaveEntitiesRequest; - -export type SaveCampaignsResponse = CampaignSaveEntitiesResponse; +export type SaveCampaignsResponse = CampaignGuidNullableSaveEntitiesResponse; export type SaveDecompoundRulesRequest = DecompoundRuleSaveSearchRulesRequest; @@ -4901,9 +4908,9 @@ export type SaveGlobalTriggerConfigurationRequest = LicensedRequest & { modifiedBy?: string | null; }; -export type SaveLocationsRequest = LocationSaveEntitiesRequest; +export type SaveLocationsRequest = LocationGuidNullableSaveEntitiesRequest; -export type SaveLocationsResponse = LocationSaveEntitiesResponse; +export type SaveLocationsResponse = LocationGuidNullableSaveEntitiesResponse; export type SaveMerchandisingRuleRequest = LicensedRequest & { rule?: BoostAndBuryRule | FilterRule | FixedPositionRule | InputModifierRule | null; @@ -5051,7 +5058,7 @@ export type SearchResponseCollection = SearchResponse & { }; export type SearchResultModifierRule = SearchRule & { - condition: SearchTermCondition | RetailMediaSearchTermCondition; + condition: SearchTermCondition | SearchTermConditionByLanguage; actions: (SearchResultModifierRuleAddFiltersAction | SearchResultModifierRuleAddTermFilterAction)[]; }; @@ -5154,15 +5161,23 @@ export interface SearchTermCondition { $type: string; kind?: "Equals" | "StartsWith" | "EndsWith" | "Contains" | null; value?: string | null; - andConditions?: (SearchTermCondition | RetailMediaSearchTermCondition)[] | null; - orConditions?: (SearchTermCondition | RetailMediaSearchTermCondition)[] | null; + andConditions?: (SearchTermCondition | SearchTermConditionByLanguage)[] | null; + orConditions?: (SearchTermCondition | SearchTermConditionByLanguage)[] | null; /** @format int32 */ minimumLength?: number | null; negated: boolean; } +export type SearchTermConditionByLanguage = SearchTermCondition & { + language?: Language | null; +}; + +export interface SearchTermConditionByLanguageCollection { + values?: SearchTermConditionByLanguage[] | null; +} + export type SearchTermModifierRule = SearchRule & { - condition: SearchTermCondition | RetailMediaSearchTermCondition; + condition: SearchTermCondition | SearchTermConditionByLanguage; actions: ( | SearchTermModifierRuleAppendToTermAction | SearchTermModifierRuleRemoveFromTermAction @@ -5706,6 +5721,10 @@ export type TrackContentCategoryViewRequest = TrackingRequest & { contentCategoryView: ContentCategoryView; }; +export type TrackContentEngagementRequest = TrackingRequest & { + contentEngagement: ContentEngagement; +}; + export type TrackContentUpdateRequest = TrackingRequest & { contentUpdate?: ContentUpdate | null; }; @@ -5722,10 +5741,6 @@ export type TrackFeedItemClickRequest = TrackingRequest & { click: FeedItemClick; }; -export type TrackFeedItemFeedbackRequest = TrackingRequest & { - feedback: FeedItemFeedback; -}; - export type TrackFeedItemPreviewRequest = TrackingRequest & { preview: FeedItemPreview; }; @@ -5750,6 +5765,10 @@ export type TrackProductCategoryViewRequest = TrackingRequest & { productCategoryView: ProductCategoryView; }; +export type TrackProductEngagementRequest = TrackingRequest & { + productEngagement: ProductEngagement; +}; + export type TrackProductUpdateRequest = TrackingRequest & { productUpdate?: ProductUpdate | null; }; diff --git a/packages/client/src/tracker.ts b/packages/client/src/tracker.ts index f8302226..fc852ec7 100644 --- a/packages/client/src/tracker.ts +++ b/packages/client/src/tracker.ts @@ -5,12 +5,14 @@ import { FeedDwell, TrackFeedDwellRequest, TrackFeedItemClickRequest, - FeedItemClick, TrackFeedItemPreviewRequest, - FeedItemPreview, - TrackFeedItemFeedbackRequest, - FeedItemFeedback, FeedItem, + ProductEngagement, + TrackProductEngagementRequest, + ContentEngagement, + TrackContentEngagementRequest, + ProductEngagementData, + ProductAndVariantId, } from './models/data-contracts'; export class Tracker extends RelewiseClient { @@ -166,6 +168,30 @@ export class Tracker extends RelewiseClient { }, options); } + public async trackProductEngagement({ user, engagement, product }: { user?: User | null, product: ProductAndVariantId, engagement: ProductEngagementData }, options?: RelewiseRequestOptions) { + return this.request('TrackProductEngagementRequest', { + $type: 'Relewise.Client.Requests.Tracking.TrackProductEngagementRequest, Relewise.Client', + productEngagement: { + $type: 'Relewise.Client.DataTypes.ProductEngagement, Relewise.Client', + user: user, + id: product, + engagement: engagement + } + }, options); + } + + public async trackContentEngagement({ user, engagement, id: contentId }: Omit, options?: RelewiseRequestOptions) { + return this.request('TrackContentEngagementRequest', { + $type: 'Relewise.Client.Requests.Tracking.TrackContentEngagementRequest, Relewise.Client', + contentEngagement: { + $type: 'Relewise.Client.DataTypes.ContentEngagement, Relewise.Client', + user: user, + id: contentId, + engagement: engagement + } + }, options); + } + public async trackFeedDwell({ user, feedId, dwellTimeMilliseconds, visibleItems }: Omit, options?: RelewiseRequestOptions) { return this.request('TrackFeedDwellRequest', { $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedDwellRequest, Relewise.Client', @@ -191,19 +217,6 @@ export class Tracker extends RelewiseClient { }, options); } - public async trackFeedItemFeedback({ user, feedId, item, kind }: Omit, options?: RelewiseRequestOptions) { - return this.request('TrackFeedItemFeedbackRequest', { - $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedItemFeedbackRequest, Relewise.Client', - feedback: { - $type: 'Relewise.Client.DataTypes.Feed.FeedItemFeedback, Relewise.Client', - user: user, - feedId: feedId, - item: item, - kind: kind - } - }, options); - } - public async trackFeedItemPreview({ user, feedId, item }: { user?: User | null; feedId: string; item?: FeedItem }, options?: RelewiseRequestOptions) { return this.request('TrackFeedItemPreviewRequest', { $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedItemPreviewRequest, Relewise.Client', diff --git a/packages/client/tests/integration-tests/tracker.integration.test.ts b/packages/client/tests/integration-tests/tracker.integration.test.ts index d583ab1a..375df211 100644 --- a/packages/client/tests/integration-tests/tracker.integration.test.ts +++ b/packages/client/tests/integration-tests/tracker.integration.test.ts @@ -1,4 +1,4 @@ -import { error } from 'console'; +import { error } from 'console'; import { DataValueFactory, ProblemDetailsError, Tracker, UserFactory } from '../../src'; import { test, expect } from '@jest/globals' @@ -6,7 +6,7 @@ const { npm_config_API_KEY: API_KEY, npm_config_DATASET_ID: DATASET_ID, npm_conf const tracker = new Tracker(DATASET_ID!, API_KEY!, { serverUrl: SERVER_URL }); -test('Track Order', async() => { +test('Track Order', async () => { const result = await tracker.trackOrder({ lineItems: [ { @@ -33,7 +33,7 @@ test('Track Order', async() => { expect(result).toBeUndefined(); }); -test('Track Cart', async() => { +test('Track Cart', async () => { const result = await tracker.trackCart({ lineItems: [ { @@ -60,7 +60,7 @@ test('Track Cart', async() => { expect(result).toBeUndefined(); }); -test('Track Product View', async() => { +test('Track Product View', async () => { const result = await tracker.trackProductView({ productId: '1', user: UserFactory.anonymous(), @@ -69,7 +69,7 @@ test('Track Product View', async() => { expect(result).toBeUndefined(); }); -test('Track Product View', async() => { +test('Track Product View', async () => { const result = await tracker.trackProductView({ productId: '2', user: UserFactory.anonymous(), @@ -78,7 +78,7 @@ test('Track Product View', async() => { expect(result).toBeUndefined(); }); -test('Track Product Category View', async() => { +test('Track Product Category View', async () => { const result = await tracker.trackProductCategoryView({ idPath: ['c1'], user: UserFactory.anonymous(), @@ -87,7 +87,7 @@ test('Track Product Category View', async() => { expect(result).toBeUndefined(); }); -test('Track Content View', async() => { +test('Track Content View', async () => { const result = await tracker.trackContentView({ contentId: '1', user: UserFactory.anonymous(), @@ -96,7 +96,7 @@ test('Track Content View', async() => { expect(result).toBeUndefined(); }); -test('Track Content View', async() => { +test('Track Content View', async () => { const result = await tracker.trackContentView({ contentId: '2', user: UserFactory.anonymous(), @@ -120,7 +120,7 @@ test('Track Content View', async() => { expect(result).toBeUndefined(); }); -test('Track Content Category View', async() => { +test('Track Content Category View', async () => { const result = await tracker.trackContentCategoryView({ idPath: ['c1'], user: UserFactory.anonymous(), @@ -129,7 +129,7 @@ test('Track Content Category View', async() => { expect(result).toBeUndefined(); }); -test('Track Brand View', async() => { +test('Track Brand View', async () => { const result = await tracker.trackBrandView({ brandId: 'b-1', user: UserFactory.anonymous(), @@ -138,7 +138,7 @@ test('Track Brand View', async() => { expect(result).toBeUndefined(); }); -test('Track Search Term', async() => { +test('Track Search Term', async () => { const result = await tracker.trackSearchTerm({ term: 'term', @@ -149,7 +149,7 @@ test('Track Search Term', async() => { expect(result).toBeUndefined(); }); -test('Track User Update', async() => { +test('Track User Update', async () => { const user = UserFactory.byTemporaryId('tempId', { email: 'integrationtests@relewise.com', identifiers: { @@ -164,7 +164,7 @@ test('Track User Update', async() => { expect(result).toBeUndefined(); }); -test('Track Product View with invalid key', async() => { +test('Track Product View with invalid key', async () => { await new Tracker(DATASET_ID!, '12', { serverUrl: SERVER_URL }).trackProductView({ productId: '2', @@ -178,8 +178,8 @@ test('Track Product View with invalid key', async() => { }); }); -test('Track Product View without id', async() => { - await expect(async() => { +test('Track Product View without id', async () => { + await expect(async () => { return await tracker.trackProductView({ productId: null, user: UserFactory.anonymous(), @@ -187,7 +187,7 @@ test('Track Product View without id', async() => { }).rejects.toThrow(); }); -test('Track Product View without id', async() => { +test('Track Product View without id', async () => { try { await tracker.trackProductView({ productId: null, @@ -199,8 +199,23 @@ test('Track Product View without id', async() => { } }); -test('Track Product View on a Dataset that does not exist', async() => { - await expect(async() => { +test('Track Product Engagement', async () => { + try { + await tracker.trackProductEngagement({ + product: { productId: "1" }, + engagement: { + sentiment: 'Like' + }, + user: UserFactory.byAuthenticatedId("1"), + }); + } + catch (e) { + expect(e).toBeDefined(); + } +}); + +test('Track Product View on a Dataset that does not exist', async () => { + await expect(async () => { const tracker = new Tracker("00000000-0000-0000-0000-000000000000", API_KEY!, { serverUrl: SERVER_URL }); return await tracker.trackProductView({ From 8463524e3e026b54dc3906f06f792f3c57dcd5f6 Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Thu, 18 Sep 2025 10:19:01 +0200 Subject: [PATCH 05/14] fix exports --- .../builders/recommendation/feed/feedCompositionBuilder.ts | 4 ++-- packages/client/src/builders/recommendation/feed/index.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts b/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts index 9873c1a3..16af4449 100644 --- a/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts +++ b/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts @@ -1,6 +1,6 @@ -import { FilterBuilder } from 'src/builders/filterBuilder'; +import { FilterBuilder } from '../../filterBuilder'; import { FeedComposition, Int32Range } from '../../../models/data-contracts'; -import { RelevanceModifierBuilder } from 'src/builders/relevanceModifierBuilder'; +import { RelevanceModifierBuilder } from '../../relevanceModifierBuilder'; export class FeedCompositionBuilder { private composition: FeedComposition; diff --git a/packages/client/src/builders/recommendation/feed/index.ts b/packages/client/src/builders/recommendation/feed/index.ts index fdcc82b0..1d8680c2 100644 --- a/packages/client/src/builders/recommendation/feed/index.ts +++ b/packages/client/src/builders/recommendation/feed/index.ts @@ -1,2 +1,3 @@ +export * from './feedCompositionBuilder'; export * from './feedRecommendationInitializationBuilder'; export * from './feedRecommendationNextItemsBuilder'; \ No newline at end of file From b67204f06b87585b27322a6b355513dd39150dc0 Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Thu, 18 Sep 2025 12:23:42 +0200 Subject: [PATCH 06/14] fix test --- .../batchContentRecommendations.integration.test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts b/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts index f9faf3f7..b110bbe0 100644 --- a/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts +++ b/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts @@ -29,13 +29,17 @@ test('Batched Content Reommendations', async () => { test('Batched Content Reommendations', async () => { - const t = new FeedRecommendationInitializationBuilder({ minimumPageSize: 10 }, settings) + const request = new FeedRecommendationInitializationBuilder({ minimumPageSize: 10 }, settings) .addCompostion({ type: 'Product', count: { lowerBoundInclusive: 1, upperBoundInclusive: 2 } }, b => b - .filters(f => f.addContentCategoryIdFilter('Imm', 2)) + .filters(f => f.addContentCategoryIdFilter('ImmediateParent', "2")) .rotationLimit(1) ); + + const result = await recommender.recommendFeedRecommendationInitialization(request.build()); + + expect(result).not.toBe(undefined); }); \ No newline at end of file From bf8c35d2e3548dd193a2f73549e3a0b4d9784ee3 Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Mon, 20 Oct 2025 09:58:38 +0200 Subject: [PATCH 07/14] wip --- packages/client/package.json | 2 +- .../feed/feedCompositionBuilder.ts | 25 +- ...feedRecommendationInitializationBuilder.ts | 15 +- packages/client/src/models/data-contracts.ts | 387 +++++++++++++++++- packages/client/src/tracker.ts | 12 +- 5 files changed, 423 insertions(+), 18 deletions(-) diff --git a/packages/client/package.json b/packages/client/package.json index 61518b0b..cfd89d71 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -32,7 +32,7 @@ "prebuild:types": "rimraf ./build", "build:types": "tsc -p ./tsconfig.json --outDir build --declaration true && api-extractor run", "clean": "rimraf ./build ./dist ./docs", - "gen-api": "swagger-typescript-api -p https://sandbox-api.relewise.com/33126744-648a-441a-9c61-091ae00333ad/public/swagger.json -o src/models --modular --no-client --enum-names-as-values && node fix-exports.js", + "gen-api": "swagger-typescript-api -p https://api.relewise.com/public/swagger.json -o src/models --modular --no-client --enum-names-as-values && node fix-exports.js", "gen-api-dev": "swagger-typescript-api -p swagger.json -o src/models --modular --no-client --enum-names-as-values && node fix-exports.js", "publish": "npm run gen-api && npm run build && npm run build:types" }, diff --git a/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts b/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts index 16af4449..b17e192a 100644 --- a/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts +++ b/packages/client/src/builders/recommendation/feed/feedCompositionBuilder.ts @@ -2,14 +2,21 @@ import { FilterBuilder } from '../../filterBuilder'; import { FeedComposition, Int32Range } from '../../../models/data-contracts'; import { RelevanceModifierBuilder } from '../../relevanceModifierBuilder'; +export type FeedCompositionOptions = { + type: 'Product' | 'Content'; + count: Int32Range; + name?: string; +}; + export class FeedCompositionBuilder { private composition: FeedComposition; - constructor({ type, count }: { type: 'Product' | 'Content', count: Int32Range }) { + constructor({ type, count, name }: FeedCompositionOptions) { this.composition = { includeEmptyResults: false, type, count, + name }; } @@ -19,13 +26,25 @@ export class FeedCompositionBuilder { return this; } - public rotationLimit(limit: number): this { + public rotationLimit(limit: number | null): this { this.composition.rotationLimit = limit; return this; } - public fill(options: { type: 'Product' | 'Content', count: Int32Range }, fill: (fillBuilder: FeedCompositionBuilder) => void): this { + public name(name: string | null): this { + this.composition.name = name; + + return this; + } + + public count(count: Int32Range): this { + this.composition.count = count; + + return this; + } + + public fill(options: FeedCompositionOptions, fill: (fillBuilder: FeedCompositionBuilder) => void): this { const builder = new FeedCompositionBuilder(options); fill(builder); this.composition.fill = builder.build(); diff --git a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts index 4a5bf9fc..2026b52d 100644 --- a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts +++ b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts @@ -1,13 +1,12 @@ import { Settings } from '../../../builders/settings'; -import { Feed, FeedComposition, FeedRecommendationInitializationRequest, FeedSeed, Int32Range, SelectedContentPropertiesSettings, SelectedProductPropertiesSettings, SelectedVariantPropertiesSettings } from '../../../models/data-contracts'; +import { Feed, FeedComposition, FeedRecommendationInitializationRequest, FeedSeed, SelectedContentPropertiesSettings, SelectedProductPropertiesSettings, SelectedVariantPropertiesSettings } from '../../../models/data-contracts'; import { RecommendationRequestBuilder } from '../recommendationRequestBuilder'; -import { FeedCompositionBuilder } from './feedCompositionBuilder'; +import { FeedCompositionBuilder, FeedCompositionOptions } from './feedCompositionBuilder'; export class FeedRecommendationInitializationBuilder extends RecommendationRequestBuilder { private feed: Feed; - constructor({ minimumPageSize }: { minimumPageSize: number }, - settings: Settings) { + constructor({ minimumPageSize }: { minimumPageSize: number }, settings: Settings) { super(settings); this.feed = { @@ -38,7 +37,13 @@ export class FeedRecommendationInitializationBuilder extends RecommendationReque return this; } - public addCompostion(options: { type: 'Product' | 'Content', count: Int32Range }, builderFn: (fillBuilder: FeedCompositionBuilder) => void): this { + /** + * Adds a composition to the feed. + * @param options + * @param builderFn + * @returns + */ + public addCompostion(options: FeedCompositionOptions, builderFn: (fillBuilder: FeedCompositionBuilder) => void): this { this.feed.compositions ??= []; const builder = new FeedCompositionBuilder(options); diff --git a/packages/client/src/models/data-contracts.ts b/packages/client/src/models/data-contracts.ts index 061d4910..fc303703 100644 --- a/packages/client/src/models/data-contracts.ts +++ b/packages/client/src/models/data-contracts.ts @@ -190,9 +190,13 @@ export type AndFilter = Filter & { | ContentDataFilter | ContentDataHasKeyFilter | ContentDisabledFilter + | ContentEngagementFilter | ContentHasCategoriesFilter | ContentIdFilter | ContentRecentlyViewedByUserFilter + | DisplayAdDataFilter + | DisplayAdIdFilter + | DisplayAdTemplateIdFilter | OrFilter | ProductAndVariantIdFilter | ProductAssortmentFilter @@ -211,6 +215,7 @@ export type AndFilter = Filter & { | ProductDataHasKeyFilter | ProductDisabledFilter | ProductDisplayNameFilter + | ProductEngagementFilter | ProductHasCategoriesFilter | ProductHasVariantsFilter | ProductIdFilter @@ -229,6 +234,7 @@ export type AndFilter = Filter & { | VariantDataFilter | VariantDataHasKeyFilter | VariantDisabledFilter + | VariantEngagementFilter | VariantIdFilter | VariantListPriceFilter | VariantSalesPriceFilter @@ -280,6 +286,7 @@ export type BatchedTrackingRequest = TrackingRequest & { | ContentEngagement | ContentUpdate | ContentView + | DisplayAdClick | Order | ProductAdministrativeAction | ProductCategoryAdministrativeAction @@ -584,6 +591,33 @@ export type Campaign = CampaignEntityStateGuidNullableCampaignMetadataValuesReta export interface CampaignAnalytics { products?: CampaignAnalyticsProductAnalytics | null; + displayAds?: CampaignAnalyticsDisplayAdAnalytics | null; +} + +export interface CampaignAnalyticsDisplayAdAnalytics { + timeSeries?: CampaignAnalyticsDisplayAdAnalyticsPeriodMetrics[] | null; + /** @format int32 */ + promotions: number; + promotedDisplayAds?: CampaignAnalyticsDisplayAdAnalyticsPromotedDisplayAdMetrics[] | null; +} + +export interface CampaignAnalyticsDisplayAdAnalyticsPeriodMetrics { + /** @format date-time */ + periodFromUtc: string; + /** @format int32 */ + views: number; + /** @format int32 */ + clicks: number; +} + +export interface CampaignAnalyticsDisplayAdAnalyticsPromotedDisplayAdMetrics { + displayAdId?: string | null; + /** @format int32 */ + promotions: number; + /** @format int32 */ + lastClickedUnixMinutes: number; + /** @format int32 */ + numberOfTimesClicked: number; } export interface CampaignAnalyticsProductAnalytics { @@ -619,7 +653,8 @@ export type CampaignAnalyticsRequest = LicensedRequest & { /** @format uuid */ id: string; periodUtc: DateTimeRange; - filters?: FilterCollection | null; + productFilters?: FilterCollection | null; + displayAdFilters?: FilterCollection | null; }; export type CampaignAnalyticsResponse = TimedResponse & { @@ -892,6 +927,13 @@ export interface Channel { export type ClearTextParser = Parser; +export interface ClickedByUserInfo { + /** @format date-time */ + mostRecentlyClickedUtc: string; + /** @format int32 */ + totalNumberOfTimesClicked: number; +} + export interface Company { id: string; parent?: Company | null; @@ -1221,6 +1263,19 @@ export interface ContentEngagementData { isFavorite?: boolean | null; } +export type ContentEngagementFilter = Filter & { + sentiment?: "Neutral" | "Like" | "Dislike" | null; + isFavorite?: boolean | null; +}; + +export type ContentEngagementRelevanceModifier = RelevanceModifier & { + sentiment?: "Neutral" | "Like" | "Dislike" | null; + isFavorite?: boolean | null; + /** @format double */ + multiplyWeightBy: number; + negated: boolean; +}; + export type ContentFacetQuery = FacetQuery & { items: ( | ContentAssortmentFacet @@ -1410,6 +1465,7 @@ export interface ContentResult { viewedByUser?: ViewedByUserInfo | null; custom?: Record; highlight?: HighlightResult | null; + userEngagement?: ContentEngagementData | null; } export interface ContentResultDetails { @@ -1430,6 +1486,7 @@ export interface ContentResultDetails { disabled: boolean; deleted: boolean; custom?: Record; + userEngagement?: ContentEngagementData | null; } export type ContentSearchRequest = PaginatedSearchRequest & { @@ -1850,6 +1907,213 @@ export type DeleteTriggerConfigurationRequest = LicensedRequest & { id: string; }; +export type DisplayAd = DisplayAdEntityStateStringDisplayAdMetadataValuesRetailMediaEntity & { + name: string; + /** @format uuid */ + advertiserId: string; + /** @format uuid */ + templateId: string; + data?: Record; +}; + +export type DisplayAdClick = Trackable & { + user?: User | null; + displayAdId: string; + /** @format uuid */ + campaignId: string; +}; + +export type DisplayAdDataFilter = DataFilter; + +export interface DisplayAdEntityStateStringDisplayAdMetadataValuesDisplayAdsRequestSortByDisplayAdsRequestEntityFiltersEntitiesRequest { + $type: string; + filters?: DisplayAdsRequestEntityFilters | null; + sorting?: DisplayAdsRequestSortBySorting | null; + /** @format int32 */ + skip: number; + /** @format int32 */ + take: number; + custom?: Record; +} + +export interface DisplayAdEntityStateStringDisplayAdMetadataValuesRetailMediaEntity { + $type: string; + state: "Active" | "Inactive" | "Archived"; + metadata: DisplayAdMetadataValues; + id: string; +} + +export type DisplayAdIdFilter = Filter & { + ids?: string[] | null; +}; + +export type DisplayAdMetadataValues = MetadataValues; + +export type DisplayAdPromotion = Promotion & { + productFilters?: FilterCollection | null; + conditions?: DisplayAdPromotionPromotionConditions | null; + displayAdFilters?: FilterCollection | null; +}; + +export type DisplayAdPromotionPromotionConditions = RetailMediaConditions & { + searchTerm?: SearchTermConditionByLanguageCollection | null; + requestFilters?: RequestFilterCriteria | null; +}; + +export type DisplayAdPromotionSpecification = PromotionSpecification & { + promotableDisplayAdTemplateIds?: string[] | null; + promotableDisplayAdTemplateFilters?: FilterCollection | null; +}; + +export interface DisplayAdResult { + displayAdId: string; + name?: string | null; + data?: Record; + clickedByUserInfo?: ClickedByUserInfo | null; +} + +export interface DisplayAdStringDisplayAdEntityStateEntityResponse { + $type: string; + entities?: DisplayAd[] | null; + /** @format int32 */ + hits: number; + hitsPerState?: { + /** @format int32 */ + Active: number; + /** @format int32 */ + Inactive: number; + /** @format int32 */ + Archived: number; + } | null; + statistics?: Statistics | null; +} + +export interface DisplayAdStringSaveEntitiesRequest { + $type: string; + entities: DisplayAd[]; + modifiedBy: string; + custom?: Record; +} + +export interface DisplayAdStringSaveEntitiesResponse { + $type: string; + entities?: DisplayAd[] | null; + statistics?: Statistics | null; +} + +export type DisplayAdTemplate = + DisplayAdTemplateEntityStateGuidNullableDisplayAdTemplateMetadataValuesRetailMediaEntity & { + name: string; + fields: DisplayAdTemplateFieldDefinition[]; + }; + +export interface DisplayAdTemplateEntityStateGuidDisplayAdTemplateMetadataValuesDisplayAdTemplatesRequestSortByDisplayAdTemplatesRequestEntityFiltersEntitiesRequest { + $type: string; + filters?: DisplayAdTemplatesRequestEntityFilters | null; + sorting?: DisplayAdTemplatesRequestSortBySorting | null; + /** @format int32 */ + skip: number; + /** @format int32 */ + take: number; + custom?: Record; +} + +export interface DisplayAdTemplateEntityStateGuidNullableDisplayAdTemplateMetadataValuesRetailMediaEntity { + $type: string; + state: "Active" | "Inactive" | "Archived"; + metadata: DisplayAdTemplateMetadataValues; + /** @format uuid */ + id?: string | null; +} + +export interface DisplayAdTemplateFieldDefinition { + name: string; + type: + | "String" + | "Double" + | "Boolean" + | "Multilingual" + | "Money" + | "MultiCurrency" + | "StringList" + | "DoubleList" + | "BooleanList" + | "MultilingualCollection" + | "Object" + | "ObjectList"; + metadata?: Record; +} + +export interface DisplayAdTemplateGuidNullableDisplayAdTemplateEntityStateEntityResponse { + $type: string; + entities?: DisplayAdTemplate[] | null; + /** @format int32 */ + hits: number; + hitsPerState?: { + /** @format int32 */ + Active: number; + /** @format int32 */ + Inactive: number; + /** @format int32 */ + Archived: number; + } | null; + statistics?: Statistics | null; +} + +export interface DisplayAdTemplateGuidNullableSaveEntitiesRequest { + $type: string; + entities: DisplayAdTemplate[]; + modifiedBy: string; + custom?: Record; +} + +export interface DisplayAdTemplateGuidNullableSaveEntitiesResponse { + $type: string; + entities?: DisplayAdTemplate[] | null; + statistics?: Statistics | null; +} + +export type DisplayAdTemplateIdFilter = Filter & { + ids?: string[] | null; +}; + +export type DisplayAdTemplateMetadataValues = MetadataValues; + +export type DisplayAdTemplatesRequest = + DisplayAdTemplateEntityStateGuidDisplayAdTemplateMetadataValuesDisplayAdTemplatesRequestSortByDisplayAdTemplatesRequestEntityFiltersEntitiesRequest; + +export type DisplayAdTemplatesRequestEntityFilters = + RetailMediaEntity3DisplayAdTemplateEntityStateGuidDisplayAdTemplateMetadataValuesRetailMediaEntity3EntityFilters & { + ids?: string[] | null; + keys?: string[] | null; + filters?: FilterCollection | null; + }; + +export interface DisplayAdTemplatesRequestSortBySorting { + sortBy: "Created" | "Modified" | "Name"; + sortOrder: "Ascending" | "Descending"; +} + +export type DisplayAdTemplatesResponse = DisplayAdTemplateGuidNullableDisplayAdTemplateEntityStateEntityResponse; + +export type DisplayAdsRequest = + DisplayAdEntityStateStringDisplayAdMetadataValuesDisplayAdsRequestSortByDisplayAdsRequestEntityFiltersEntitiesRequest; + +export type DisplayAdsRequestEntityFilters = + RetailMediaEntity3DisplayAdEntityStateStringDisplayAdMetadataValuesRetailMediaEntity3EntityFilters & { + ids?: string[] | null; + advertiserIds?: string[] | null; + templateIds?: string[] | null; + filters?: FilterCollection | null; + }; + +export interface DisplayAdsRequestSortBySorting { + sortBy: "Created" | "Modified" | "Name"; + sortOrder: "Ascending" | "Descending"; +} + +export type DisplayAdsResponse = DisplayAdStringDisplayAdEntityStateEntityResponse; + export type DistinctCondition = ValueCondition & { /** @format int32 */ numberOfOccurrencesAllowedWithTheSameValue: number; @@ -2192,7 +2456,7 @@ export interface FeedCompositionResult { } export type FeedDwell = Trackable & { - user: User; + user?: User | null; /** @format uuid */ feedId: string; /** @format int32 */ @@ -2286,9 +2550,13 @@ export interface FilterCollection { | ContentDataFilter | ContentDataHasKeyFilter | ContentDisabledFilter + | ContentEngagementFilter | ContentHasCategoriesFilter | ContentIdFilter | ContentRecentlyViewedByUserFilter + | DisplayAdDataFilter + | DisplayAdIdFilter + | DisplayAdTemplateIdFilter | OrFilter | ProductAndVariantIdFilter | ProductAssortmentFilter @@ -2307,6 +2575,7 @@ export interface FilterCollection { | ProductDataHasKeyFilter | ProductDisabledFilter | ProductDisplayNameFilter + | ProductEngagementFilter | ProductHasCategoriesFilter | ProductHasVariantsFilter | ProductIdFilter @@ -2325,6 +2594,7 @@ export interface FilterCollection { | VariantDataFilter | VariantDataHasKeyFilter | VariantDisabledFilter + | VariantEngagementFilter | VariantIdFilter | VariantListPriceFilter | VariantSalesPriceFilter @@ -2785,6 +3055,7 @@ export interface LocationPlacement { key?: string | null; variations?: LocationPlacementVariationCollection | null; thresholds?: ScoreThresholds | null; + displayAdTemplateFilters?: FilterCollection | null; } export interface LocationPlacementCollection { @@ -3014,9 +3285,13 @@ export type OrFilter = Filter & { | ContentDataFilter | ContentDataHasKeyFilter | ContentDisabledFilter + | ContentEngagementFilter | ContentHasCategoriesFilter | ContentIdFilter | ContentRecentlyViewedByUserFilter + | DisplayAdDataFilter + | DisplayAdIdFilter + | DisplayAdTemplateIdFilter | OrFilter | ProductAndVariantIdFilter | ProductAssortmentFilter @@ -3035,6 +3310,7 @@ export type OrFilter = Filter & { | ProductDataHasKeyFilter | ProductDisabledFilter | ProductDisplayNameFilter + | ProductEngagementFilter | ProductHasCategoriesFilter | ProductHasVariantsFilter | ProductIdFilter @@ -3053,6 +3329,7 @@ export type OrFilter = Filter & { | VariantDataFilter | VariantDataHasKeyFilter | VariantDisabledFilter + | VariantEngagementFilter | VariantIdFilter | VariantListPriceFilter | VariantSalesPriceFilter @@ -3118,6 +3395,7 @@ export interface OverriddenSelectedContentPropertiesSettings { allData?: boolean | null; viewedByUserInfo?: boolean | null; dataKeys?: string[] | null; + userEngagement?: boolean | null; } export interface OverriddenSelectedProductPropertiesSettings { @@ -3132,6 +3410,7 @@ export interface OverriddenSelectedProductPropertiesSettings { allVariants?: boolean | null; dataKeys?: string[] | null; score?: SelectedScorePropertiesSettings | null; + userEngagement?: boolean | null; } export interface OverriddenSelectedVariantPropertiesSettings { @@ -3142,6 +3421,7 @@ export interface OverriddenSelectedVariantPropertiesSettings { allData?: boolean | null; dataKeys?: string[] | null; specificationKeys?: string[] | null; + userEngagement?: boolean | null; } export interface PaginatedSearchRequest { @@ -3856,6 +4136,19 @@ export interface ProductEngagementData { isFavorite?: boolean | null; } +export type ProductEngagementFilter = Filter & { + sentiment?: "Neutral" | "Like" | "Dislike" | null; + isFavorite?: boolean | null; +}; + +export type ProductEngagementRelevanceModifier = RelevanceModifier & { + sentiment?: "Neutral" | "Like" | "Dislike" | null; + isFavorite?: boolean | null; + /** @format double */ + multiplyWeightBy: number; + negated: boolean; +}; + export type ProductFacetQuery = FacetQuery & { items: ( | ContentAssortmentFacet @@ -4138,6 +4431,7 @@ export type ProductPromotion = Promotion & { export type ProductPromotionPromotionConditions = RetailMediaConditions & { searchTerm?: SearchTermConditionByLanguageCollection | null; + requestFilters?: RequestFilterCriteria | null; }; export type ProductPromotionSpecification = PromotionSpecification & { @@ -4388,6 +4682,7 @@ export interface ProductResult { filteredVariants?: VariantResult[] | null; highlight?: HighlightResult | null; score?: Score | null; + userEngagement?: ProductEngagementData | null; } export interface ProductResultDetails { @@ -4422,6 +4717,7 @@ export interface ProductResultDetails { salesPrice?: MultiCurrency | null; brand?: BrandResultDetails | null; filteredVariants?: VariantResultDetails[] | null; + userEngagement?: ProductEngagementData | null; } export type ProductSalesPriceFilter = Filter & { @@ -4551,9 +4847,11 @@ export interface Promotion { } export interface PromotionCollection { - promotions: ProductPromotion[]; + promotions: (DisplayAdPromotion | ProductPromotion)[]; } +export type PromotionDisplayAdsVariationPromotionPriority = PromotionVariationPromotionPriority; + export interface PromotionLocation { key: string; placements?: PromotionLocationPlacementCollection | null; @@ -4572,12 +4870,15 @@ export interface PromotionLocationPlacementCollection { items?: PromotionLocationPlacement[] | null; } +export type PromotionProductsVariationPromotionPriority = PromotionVariationPromotionPriority; + export interface PromotionSpecification { $type: string; } export interface PromotionSpecificationCollection { productPromotion?: ProductPromotionSpecification | null; + displayAdPromotion?: DisplayAdPromotionSpecification | null; } export interface PromotionSpecificationVariation { @@ -4585,7 +4886,23 @@ export interface PromotionSpecificationVariation { } export interface PromotionSpecificationVariationCollection { + /** @deprecated */ productPromotion?: ProductPromotionSpecificationVariation | null; + variationPromotion?: PromotionVariationPromotion | null; +} + +export type PromotionVariationPromotion = PromotionSpecificationVariation & { + /** @format int32 */ + maxCount: number; + /** @format int32 */ + preferredNumberOfProducts?: number | null; + /** @format int32 */ + preferredNumberOfDisplayAds?: number | null; + priority?: PromotionProductsVariationPromotionPriority | PromotionDisplayAdsVariationPromotionPriority | null; +}; + +export interface PromotionVariationPromotionPriority { + $type: string; } export interface PurchaseQualifiers { @@ -4776,12 +5093,14 @@ export interface RelevanceModifierCollection { | ContentCategoryDataRelevanceModifier | ContentCategoryRecentlyViewedByUserRelevanceModifier | ContentDataRelevanceModifier + | ContentEngagementRelevanceModifier | ContentRecentlyViewedByUserRelevanceModifier | ProductAssortmentRelevanceModifier | ProductCategoryDataRelevanceModifier | ProductCategoryIdRelevanceModifier | ProductCategoryRecentlyViewedByUserRelevanceModifier | ProductDataRelevanceModifier + | ProductEngagementRelevanceModifier | ProductIdRelevanceModifier | ProductListPriceRelevanceModifier | ProductRecentlyPurchasedByCompanyRelevanceModifier @@ -4794,6 +5113,7 @@ export interface RelevanceModifierCollection { | UserFavoriteProductRelevanceModifier | VariantAssortmentRelevanceModifier | VariantDataRelevanceModifier + | VariantEngagementRelevanceModifier | VariantIdRelevanceModifier | VariantListPriceRelevanceModifier | VariantSalesPriceRelevanceModifier @@ -4846,6 +5166,18 @@ export interface RetailMediaEntity3CampaignEntityStateGuidNullableCampaignMetada states?: ("Proposed" | "Approved" | "Archived")[] | null; } +export interface RetailMediaEntity3DisplayAdEntityStateStringDisplayAdMetadataValuesRetailMediaEntity3EntityFilters { + $type: string; + term?: string | null; + states?: ("Active" | "Inactive" | "Archived")[] | null; +} + +export interface RetailMediaEntity3DisplayAdTemplateEntityStateGuidDisplayAdTemplateMetadataValuesRetailMediaEntity3EntityFilters { + $type: string; + term?: string | null; + states?: ("Active" | "Inactive" | "Archived")[] | null; +} + export interface RetailMediaEntity3LocationEntityStateGuidLocationMetadataValuesRetailMediaEntity3EntityFilters { $type: string; term?: string | null; @@ -4854,6 +5186,7 @@ export interface RetailMediaEntity3LocationEntityStateGuidLocationMetadataValues export interface RetailMediaQuery { location: RetailMediaQueryLocationSelector; + settings?: RetailMediaQuerySettings | null; } export interface RetailMediaQueryLocationSelector { @@ -4866,6 +5199,10 @@ export interface RetailMediaQueryPlacementSelector { key: string; } +export interface RetailMediaQuerySettings { + selectedDisplayAdProperties?: SelectedDisplayAdPropertiesSettings | null; +} + export interface RetailMediaQueryVariationSelector { key: string; } @@ -4880,6 +5217,11 @@ export interface RetailMediaResultPlacement { export interface RetailMediaResultPlacementResultEntity { promotedProduct?: RetailMediaResultPlacementResultEntityProduct | null; + promotedDisplayAd?: RetailMediaResultPlacementResultEntityDisplayAd | null; +} + +export interface RetailMediaResultPlacementResultEntityDisplayAd { + result: DisplayAdResult; } export interface RetailMediaResultPlacementResultEntityProduct { @@ -4898,6 +5240,14 @@ export type SaveDecompoundRulesRequest = DecompoundRuleSaveSearchRulesRequest; export type SaveDecompoundRulesResponse = DecompoundRuleSaveSearchRulesResponse; +export type SaveDisplayAdTemplatesRequest = DisplayAdTemplateGuidNullableSaveEntitiesRequest; + +export type SaveDisplayAdTemplatesResponse = DisplayAdTemplateGuidNullableSaveEntitiesResponse; + +export type SaveDisplayAdsRequest = DisplayAdStringSaveEntitiesRequest; + +export type SaveDisplayAdsResponse = DisplayAdStringSaveEntitiesResponse; + export type SaveGlobalRetailMediaConfigurationRequest = LicensedRequest & { configuration?: GlobalRetailMediaConfiguration | null; modifiedBy?: string | null; @@ -5315,6 +5665,14 @@ export interface SelectedContentPropertiesSettings { allData: boolean; viewedByUserInfo: boolean; dataKeys?: string[] | null; + userEngagement: boolean; +} + +export interface SelectedDisplayAdPropertiesSettings { + displayName: boolean; + allData: boolean; + dataKeys?: string[] | null; + clickedByUserInfo: boolean; } export type SelectedProductCategoryPropertiesSettings = SelectedCategoryPropertiesSettings; @@ -5333,6 +5691,7 @@ export interface SelectedProductDetailsPropertiesSettings { viewedByUserCompanyInfo: boolean; purchasedByUserCompanyInfo: boolean; filteredVariants?: FilteredVariantsSettings | null; + userEngagement: boolean; } export interface SelectedProductPropertiesSettings { @@ -5350,6 +5709,7 @@ export interface SelectedProductPropertiesSettings { purchasedByUserCompanyInfo: boolean; filteredVariants?: FilteredVariantsSettings | null; score?: SelectedScorePropertiesSettings | null; + userEngagement: boolean; } export interface SelectedScorePropertiesSettings { @@ -5365,6 +5725,7 @@ export interface SelectedVariantDetailsPropertiesSettings { allData: boolean; dataKeys?: string[] | null; specificationKeys?: string[] | null; + userEngagement: boolean; } export interface SelectedVariantPropertiesSettings { @@ -5375,6 +5736,7 @@ export interface SelectedVariantPropertiesSettings { allData: boolean; dataKeys?: string[] | null; specificationKeys?: string[] | null; + userEngagement: boolean; } export interface SignificantDataValue { @@ -5733,6 +6095,10 @@ export type TrackContentViewRequest = TrackingRequest & { contentView: ContentView; }; +export type TrackDisplayAdClickRequest = TrackingRequest & { + displayAdClick: DisplayAdClick; +}; + export type TrackFeedDwellRequest = TrackingRequest & { dwell: FeedDwell; }; @@ -6071,6 +6437,19 @@ export type VariantDataRelevanceModifier = DataRelevanceModifier; export type VariantDisabledFilter = Filter; +export type VariantEngagementFilter = Filter & { + sentiment?: "Neutral" | "Like" | "Dislike" | null; + isFavorite?: boolean | null; +}; + +export type VariantEngagementRelevanceModifier = RelevanceModifier & { + sentiment?: "Neutral" | "Like" | "Dislike" | null; + isFavorite?: boolean | null; + /** @format double */ + multiplyWeightBy: number; + negated: boolean; +}; + export type VariantIdFilter = Filter & { variantIds: string[]; }; @@ -6119,6 +6498,7 @@ export interface VariantResult { listPrice?: number | null; /** @format double */ salesPrice?: number | null; + userEngagement?: ProductEngagementData | null; } export interface VariantResultDetails { @@ -6131,6 +6511,7 @@ export interface VariantResultDetails { listPrice?: MultiCurrency | null; salesPrice?: MultiCurrency | null; disabled: boolean; + userEngagement?: ProductEngagementData | null; } export type VariantSalesPriceFilter = Filter & { diff --git a/packages/client/src/tracker.ts b/packages/client/src/tracker.ts index fc852ec7..0908ee31 100644 --- a/packages/client/src/tracker.ts +++ b/packages/client/src/tracker.ts @@ -7,12 +7,12 @@ import { TrackFeedItemClickRequest, TrackFeedItemPreviewRequest, FeedItem, - ProductEngagement, TrackProductEngagementRequest, ContentEngagement, TrackContentEngagementRequest, ProductEngagementData, ProductAndVariantId, + ContentEngagementData, } from './models/data-contracts'; export class Tracker extends RelewiseClient { @@ -168,7 +168,7 @@ export class Tracker extends RelewiseClient { }, options); } - public async trackProductEngagement({ user, engagement, product }: { user?: User | null, product: ProductAndVariantId, engagement: ProductEngagementData }, options?: RelewiseRequestOptions) { + public async trackProductEngagement({ user, engagement, product }: { user: User, product: ProductAndVariantId, engagement: ProductEngagementData }, options?: RelewiseRequestOptions) { return this.request('TrackProductEngagementRequest', { $type: 'Relewise.Client.Requests.Tracking.TrackProductEngagementRequest, Relewise.Client', productEngagement: { @@ -180,7 +180,7 @@ export class Tracker extends RelewiseClient { }, options); } - public async trackContentEngagement({ user, engagement, id: contentId }: Omit, options?: RelewiseRequestOptions) { + public async trackContentEngagement({ user, engagement, contentId }: { user: User, contentId: string, engagement: ContentEngagementData }, options?: RelewiseRequestOptions) { return this.request('TrackContentEngagementRequest', { $type: 'Relewise.Client.Requests.Tracking.TrackContentEngagementRequest, Relewise.Client', contentEngagement: { @@ -192,7 +192,7 @@ export class Tracker extends RelewiseClient { }, options); } - public async trackFeedDwell({ user, feedId, dwellTimeMilliseconds, visibleItems }: Omit, options?: RelewiseRequestOptions) { + public async trackFeedDwell({ user, feedId, dwellTimeMilliseconds, visibleItems }: { user: User; feedId: string, dwellTimeMilliseconds: number, visibleItems: FeedItem[] }, options?: RelewiseRequestOptions) { return this.request('TrackFeedDwellRequest', { $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedDwellRequest, Relewise.Client', dwell: { @@ -205,7 +205,7 @@ export class Tracker extends RelewiseClient { }, options); } - public async trackFeedItemClick({ user, feedId, item }: { user?: User | null; feedId: string; item?: FeedItem }, options?: RelewiseRequestOptions) { + public async trackFeedItemClick({ user, feedId, item }: { user: User; feedId: string; item?: FeedItem }, options?: RelewiseRequestOptions) { return this.request('TrackFeedItemClickRequest', { $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedItemClickRequest, Relewise.Client', click: { @@ -217,7 +217,7 @@ export class Tracker extends RelewiseClient { }, options); } - public async trackFeedItemPreview({ user, feedId, item }: { user?: User | null; feedId: string; item?: FeedItem }, options?: RelewiseRequestOptions) { + public async trackFeedItemPreview({ user, feedId, item }: { user: User; feedId: string; item?: FeedItem }, options?: RelewiseRequestOptions) { return this.request('TrackFeedItemPreviewRequest', { $type: 'Relewise.Client.Requests.Tracking.Feed.TrackFeedItemPreviewRequest, Relewise.Client', preview: { From 4126c436b771cf45f7f39d77373e30c2b45c0544 Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Mon, 20 Oct 2025 10:01:36 +0200 Subject: [PATCH 08/14] wip --- ...feedRecommendationInitializationBuilder.ts | 6 +++-- ...ContentRecommendations.integration.test.ts | 19 +------------ .../feedRecommendations.integration.test.ts | 27 +++++++++++++++++++ 3 files changed, 32 insertions(+), 20 deletions(-) create mode 100644 packages/client/tests/integration-tests/feedRecommendations.integration.test.ts diff --git a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts index 2026b52d..84f31ca5 100644 --- a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts +++ b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts @@ -43,11 +43,13 @@ export class FeedRecommendationInitializationBuilder extends RecommendationReque * @param builderFn * @returns */ - public addCompostion(options: FeedCompositionOptions, builderFn: (fillBuilder: FeedCompositionBuilder) => void): this { + public addCompostion(options: FeedCompositionOptions, builderFn?: (fillBuilder: FeedCompositionBuilder) => void): this { this.feed.compositions ??= []; const builder = new FeedCompositionBuilder(options); - builderFn(builder); + if (builderFn) { + (builder); + } this.feed.compositions.push(builder.build()); diff --git a/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts b/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts index b110bbe0..19524b1f 100644 --- a/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts +++ b/packages/client/tests/integration-tests/batchContentRecommendations.integration.test.ts @@ -1,4 +1,4 @@ -import { ContentRecommendationRequestCollection, ContentsRecommendationCollectionBuilder, ContentsViewedAfterViewingContentBuilder, FeedRecommendationInitializationBuilder, PopularContentsBuilder, Recommender, UserFactory } from '../../src'; +import { ContentRecommendationRequestCollection, ContentsRecommendationCollectionBuilder, ContentsViewedAfterViewingContentBuilder, PopularContentsBuilder, Recommender, UserFactory } from '../../src'; import { test, expect } from '@jest/globals' const { npm_config_API_KEY: API_KEY, npm_config_DATASET_ID: DATASET_ID, npm_config_SERVER_URL: SERVER_URL } = process.env; @@ -25,21 +25,4 @@ test('Batched Content Reommendations', async () => { expect(result!.responses![0].recommendations?.length).toBeGreaterThan(0); expect(result!.responses![1].recommendations?.length).toBeGreaterThan(0); -}); - -test('Batched Content Reommendations', async () => { - - const request = new FeedRecommendationInitializationBuilder({ minimumPageSize: 10 }, settings) - .addCompostion({ - type: 'Product', - count: { lowerBoundInclusive: 1, upperBoundInclusive: 2 } - }, - b => b - .filters(f => f.addContentCategoryIdFilter('ImmediateParent', "2")) - .rotationLimit(1) - ); - - const result = await recommender.recommendFeedRecommendationInitialization(request.build()); - - expect(result).not.toBe(undefined); }); \ No newline at end of file diff --git a/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts b/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts new file mode 100644 index 00000000..d24c9b6d --- /dev/null +++ b/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts @@ -0,0 +1,27 @@ +import { FeedRecommendationInitializationBuilder, Recommender, UserFactory } from '../../src'; +import { test, expect } from '@jest/globals' + +const { npm_config_API_KEY: API_KEY, npm_config_DATASET_ID: DATASET_ID, npm_config_SERVER_URL: SERVER_URL } = process.env; + +const recommender = new Recommender(DATASET_ID!, API_KEY!, { serverUrl: SERVER_URL }); + +const settings = { + language: 'en-US', + currency: 'USD', + displayedAtLocation: 'Integration test', + user: UserFactory.anonymous(), +}; + +test('Feed Recommendation', async () => { + + const request = new FeedRecommendationInitializationBuilder({ minimumPageSize: 10 }, settings) + .addCompostion({ + type: 'Product', + count: { lowerBoundInclusive: 1, upperBoundInclusive: 2 } + } + ); + + const result = await recommender.recommendFeedRecommendationInitialization(request.build()); + + expect(result).not.toBe(undefined); +}); \ No newline at end of file From 8c0434be2999c3c3988cf2446cb97105a08d3c65 Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Mon, 20 Oct 2025 10:04:59 +0200 Subject: [PATCH 09/14] wip --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index cfd89d71..b5b5bc04 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@relewise/client", - "version": "2.23.0", + "version": "2.15.0", "description": "Relewise is a next generation personalization SaaS-platform, which offers functionality within product- and content recommendations and personalized search. This official SDK helps you interact with our API.", "repository": { "type": "git", From e568112794febb8ea6009846ce93d571495db4ce Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Mon, 20 Oct 2025 10:10:56 +0200 Subject: [PATCH 10/14] tweaks --- .../feed/feedRecommendationInitializationBuilder.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts index 84f31ca5..41c94b64 100644 --- a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts +++ b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts @@ -31,8 +31,11 @@ export class FeedRecommendationInitializationBuilder extends RecommendationReque * Defines how the feed will be composed, which types of entities to include, how many of each type, and any filters or relevance modifiers that should apply to each type, etc. * @param compositions */ - public compositions(compositions: FeedComposition[]): this { - this.feed.compositions = compositions; + public addCompositions(compositions: FeedComposition[]): this { + this.feed.compositions ??= []; + for (const composition of compositions) { + this.feed.compositions.push(composition); + } return this; } @@ -43,12 +46,12 @@ export class FeedRecommendationInitializationBuilder extends RecommendationReque * @param builderFn * @returns */ - public addCompostion(options: FeedCompositionOptions, builderFn?: (fillBuilder: FeedCompositionBuilder) => void): this { + public addCompostion(options: FeedCompositionOptions, builderFn?: (feedBuilder: FeedCompositionBuilder) => void): this { this.feed.compositions ??= []; const builder = new FeedCompositionBuilder(options); if (builderFn) { - (builder); + builderFn(builder); } this.feed.compositions.push(builder.build()); From da2ff5bb1b600aa39989e1eb825c81a307b3a21f Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Mon, 20 Oct 2025 13:23:17 +0200 Subject: [PATCH 11/14] wip --- packages/client/src/tracker.ts | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/packages/client/src/tracker.ts b/packages/client/src/tracker.ts index 0908ee31..8261aafe 100644 --- a/packages/client/src/tracker.ts +++ b/packages/client/src/tracker.ts @@ -2,17 +2,10 @@ import { RelewiseClient, RelewiseClientOptions, RelewiseRequestOptions } from '. import { TrackOrderRequest, TrackCartRequest, TrackProductViewRequest, TrackProductCategoryViewRequest, TrackContentViewRequest, TrackContentCategoryViewRequest, TrackBrandViewRequest, User, TrackSearchTermRequest, TrackUserUpdateRequest, DataValue, - FeedDwell, TrackFeedDwellRequest, TrackFeedItemClickRequest, TrackFeedItemPreviewRequest, FeedItem, - TrackProductEngagementRequest, - ContentEngagement, - TrackContentEngagementRequest, - ProductEngagementData, - ProductAndVariantId, - ContentEngagementData, } from './models/data-contracts'; export class Tracker extends RelewiseClient { @@ -168,29 +161,6 @@ export class Tracker extends RelewiseClient { }, options); } - public async trackProductEngagement({ user, engagement, product }: { user: User, product: ProductAndVariantId, engagement: ProductEngagementData }, options?: RelewiseRequestOptions) { - return this.request('TrackProductEngagementRequest', { - $type: 'Relewise.Client.Requests.Tracking.TrackProductEngagementRequest, Relewise.Client', - productEngagement: { - $type: 'Relewise.Client.DataTypes.ProductEngagement, Relewise.Client', - user: user, - id: product, - engagement: engagement - } - }, options); - } - - public async trackContentEngagement({ user, engagement, contentId }: { user: User, contentId: string, engagement: ContentEngagementData }, options?: RelewiseRequestOptions) { - return this.request('TrackContentEngagementRequest', { - $type: 'Relewise.Client.Requests.Tracking.TrackContentEngagementRequest, Relewise.Client', - contentEngagement: { - $type: 'Relewise.Client.DataTypes.ContentEngagement, Relewise.Client', - user: user, - id: contentId, - engagement: engagement - } - }, options); - } public async trackFeedDwell({ user, feedId, dwellTimeMilliseconds, visibleItems }: { user: User; feedId: string, dwellTimeMilliseconds: number, visibleItems: FeedItem[] }, options?: RelewiseRequestOptions) { return this.request('TrackFeedDwellRequest', { From c0fe5ab749ee8ebee1c3cf5d851b7976320f3722 Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Thu, 6 Nov 2025 08:36:49 +0100 Subject: [PATCH 12/14] fix --- packages/client/src/models/data-contracts.ts | 991 +++++++++---------- 1 file changed, 495 insertions(+), 496 deletions(-) diff --git a/packages/client/src/models/data-contracts.ts b/packages/client/src/models/data-contracts.ts index 4e2be893..c5b974b4 100644 --- a/packages/client/src/models/data-contracts.ts +++ b/packages/client/src/models/data-contracts.ts @@ -272,36 +272,36 @@ export interface AssortmentFacetResult { export type BatchedTrackingRequest = TrackingRequest & { items?: - | ( - | BrandAdministrativeAction - | BrandUpdate - | BrandView - | Cart - | CompanyAdministrativeAction - | CompanyUpdate - | ContentAdministrativeAction - | ContentCategoryAdministrativeAction - | ContentCategoryUpdate - | ContentCategoryView - | ContentEngagement - | ContentUpdate - | ContentView - | DisplayAdClick - | Order - | ProductAdministrativeAction - | ProductCategoryAdministrativeAction - | ProductCategoryUpdate - | ProductCategoryView - | ProductEngagement - | ProductUpdate - | ProductView - | SearchTerm - | UserUpdate - | FeedDwell - | FeedItemClick - | FeedItemPreview - )[] - | null; + | ( + | BrandAdministrativeAction + | BrandUpdate + | BrandView + | Cart + | CompanyAdministrativeAction + | CompanyUpdate + | ContentAdministrativeAction + | ContentCategoryAdministrativeAction + | ContentCategoryUpdate + | ContentCategoryView + | ContentEngagement + | ContentUpdate + | ContentView + | DisplayAdClick + | Order + | ProductAdministrativeAction + | ProductCategoryAdministrativeAction + | ProductCategoryUpdate + | ProductCategoryView + | ProductEngagement + | ProductUpdate + | ProductView + | SearchTerm + | UserUpdate + | FeedDwell + | FeedItemClick + | FeedItemPreview + )[] + | null; }; export interface BooleanAvailableFacetValue { @@ -824,9 +824,9 @@ export type CategoryFacetResult = StringCategoryNameAndIdResultValueFacetResult export type CategoryHierarchyFacet = CategoryPathValueFacet & { categorySelectionStrategy: "ImmediateParent" | "Ancestors" | "Descendants"; selectedPropertiesSettings?: - | SelectedContentCategoryPropertiesSettings - | SelectedProductCategoryPropertiesSettings - | null; + | SelectedContentCategoryPropertiesSettings + | SelectedProductCategoryPropertiesSettings + | null; }; export type CategoryHierarchyFacetResult = FacetResult & { @@ -1327,45 +1327,45 @@ export type ContentFacetQuery = FacetQuery & { export interface ContentFacetResult { items?: - | ( - | ProductAssortmentFacetResult - | ContentAssortmentFacetResult - | ProductCategoryAssortmentFacetResult - | BrandFacetResult - | CategoryFacetResult - | CategoryHierarchyFacetResult - | ContentDataObjectFacetResult - | ContentDataDoubleRangeFacetResult - | ContentDataDoubleRangesFacetResult - | ContentDataStringValueFacetResult - | ContentDataBooleanValueFacetResult - | ContentDataDoubleValueFacetResult - | ContentDataIntegerValueFacetResult - | DataObjectFacetResult - | DataObjectDoubleRangeFacetResult - | DataObjectDoubleRangesFacetResult - | DataObjectStringValueFacetResult - | DataObjectBooleanValueFacetResult - | DataObjectDoubleValueFacetResult - | PriceRangeFacetResult - | PriceRangesFacetResult - | ProductCategoryDataObjectFacetResult - | ProductCategoryDataDoubleRangeFacetResult - | ProductCategoryDataDoubleRangesFacetResult - | ProductCategoryDataStringValueFacetResult - | ProductCategoryDataBooleanValueFacetResult - | ProductCategoryDataDoubleValueFacetResult - | ProductDataObjectFacetResult - | ProductDataDoubleRangeFacetResult - | ProductDataDoubleRangesFacetResult - | ProductDataStringValueFacetResult - | ProductDataBooleanValueFacetResult - | ProductDataDoubleValueFacetResult - | ProductDataIntegerValueFacetResult - | RecentlyPurchasedFacetResult - | VariantSpecificationFacetResult - )[] - | null; + | ( + | ProductAssortmentFacetResult + | ContentAssortmentFacetResult + | ProductCategoryAssortmentFacetResult + | BrandFacetResult + | CategoryFacetResult + | CategoryHierarchyFacetResult + | ContentDataObjectFacetResult + | ContentDataDoubleRangeFacetResult + | ContentDataDoubleRangesFacetResult + | ContentDataStringValueFacetResult + | ContentDataBooleanValueFacetResult + | ContentDataDoubleValueFacetResult + | ContentDataIntegerValueFacetResult + | DataObjectFacetResult + | DataObjectDoubleRangeFacetResult + | DataObjectDoubleRangesFacetResult + | DataObjectStringValueFacetResult + | DataObjectBooleanValueFacetResult + | DataObjectDoubleValueFacetResult + | PriceRangeFacetResult + | PriceRangesFacetResult + | ProductCategoryDataObjectFacetResult + | ProductCategoryDataDoubleRangeFacetResult + | ProductCategoryDataDoubleRangesFacetResult + | ProductCategoryDataStringValueFacetResult + | ProductCategoryDataBooleanValueFacetResult + | ProductCategoryDataDoubleValueFacetResult + | ProductDataObjectFacetResult + | ProductDataDoubleRangeFacetResult + | ProductDataDoubleRangesFacetResult + | ProductDataStringValueFacetResult + | ProductDataBooleanValueFacetResult + | ProductDataDoubleValueFacetResult + | ProductDataIntegerValueFacetResult + | RecentlyPurchasedFacetResult + | VariantSpecificationFacetResult + )[] + | null; } export type ContentHasCategoriesFilter = Filter; @@ -1428,15 +1428,15 @@ export interface ContentRecommendationRequest { export type ContentRecommendationRequestCollection = LicensedRequest & { requests?: - | ( - | ContentsViewedAfterViewingContentRequest - | ContentsViewedAfterViewingMultipleContentsRequest - | ContentsViewedAfterViewingMultipleProductsRequest - | ContentsViewedAfterViewingProductRequest - | PersonalContentRecommendationRequest - | PopularContentsRequest - )[] - | null; + | ( + | ContentsViewedAfterViewingContentRequest + | ContentsViewedAfterViewingMultipleContentsRequest + | ContentsViewedAfterViewingMultipleProductsRequest + | ContentsViewedAfterViewingProductRequest + | PersonalContentRecommendationRequest + | PopularContentsRequest + )[] + | null; requireDistinctContentsAcrossResults: boolean; }; @@ -1665,63 +1665,63 @@ export type DataObjectFacetResult = UtilRequiredKeys & { $type: string; key?: string | null; items?: - | ( - | ProductAssortmentFacetResult - | ContentAssortmentFacetResult - | ProductCategoryAssortmentFacetResult - | BrandFacetResult - | CategoryFacetResult - | CategoryHierarchyFacetResult - | ContentDataObjectFacetResult - | ContentDataDoubleRangeFacetResult - | ContentDataDoubleRangesFacetResult - | ContentDataStringValueFacetResult - | ContentDataBooleanValueFacetResult - | ContentDataDoubleValueFacetResult - | ContentDataIntegerValueFacetResult - | DataObjectFacetResult - | DataObjectDoubleRangeFacetResult - | DataObjectDoubleRangesFacetResult - | DataObjectStringValueFacetResult - | DataObjectBooleanValueFacetResult - | DataObjectDoubleValueFacetResult - | PriceRangeFacetResult - | PriceRangesFacetResult - | ProductCategoryDataObjectFacetResult - | ProductCategoryDataDoubleRangeFacetResult - | ProductCategoryDataDoubleRangesFacetResult - | ProductCategoryDataStringValueFacetResult - | ProductCategoryDataBooleanValueFacetResult - | ProductCategoryDataDoubleValueFacetResult - | ProductDataObjectFacetResult - | ProductDataDoubleRangeFacetResult - | ProductDataDoubleRangesFacetResult - | ProductDataStringValueFacetResult - | ProductDataBooleanValueFacetResult - | ProductDataDoubleValueFacetResult - | ProductDataIntegerValueFacetResult - | RecentlyPurchasedFacetResult - | VariantSpecificationFacetResult - )[] - | null; + | ( + | ProductAssortmentFacetResult + | ContentAssortmentFacetResult + | ProductCategoryAssortmentFacetResult + | BrandFacetResult + | CategoryFacetResult + | CategoryHierarchyFacetResult + | ContentDataObjectFacetResult + | ContentDataDoubleRangeFacetResult + | ContentDataDoubleRangesFacetResult + | ContentDataStringValueFacetResult + | ContentDataBooleanValueFacetResult + | ContentDataDoubleValueFacetResult + | ContentDataIntegerValueFacetResult + | DataObjectFacetResult + | DataObjectDoubleRangeFacetResult + | DataObjectDoubleRangesFacetResult + | DataObjectStringValueFacetResult + | DataObjectBooleanValueFacetResult + | DataObjectDoubleValueFacetResult + | PriceRangeFacetResult + | PriceRangesFacetResult + | ProductCategoryDataObjectFacetResult + | ProductCategoryDataDoubleRangeFacetResult + | ProductCategoryDataDoubleRangesFacetResult + | ProductCategoryDataStringValueFacetResult + | ProductCategoryDataBooleanValueFacetResult + | ProductCategoryDataDoubleValueFacetResult + | ProductDataObjectFacetResult + | ProductDataDoubleRangeFacetResult + | ProductDataDoubleRangesFacetResult + | ProductDataStringValueFacetResult + | ProductDataBooleanValueFacetResult + | ProductDataDoubleValueFacetResult + | ProductDataIntegerValueFacetResult + | RecentlyPurchasedFacetResult + | VariantSpecificationFacetResult + )[] + | null; filter?: DataObjectFilter | null; evaluationMode: "And" | "Or"; }; export interface DataObjectFilter { conditions?: - | ( - | ObjectValueContainsCondition - | ObjectValueEqualsCondition - | ObjectValueGreaterThanCondition - | ObjectValueInRangeCondition - | ObjectValueIsSubsetOfCondition - | ObjectValueLessThanCondition - | ObjectValueMaxByCondition - | ObjectValueMinByCondition - | ObjectValueRelativeDateTimeCondition - )[] - | null; + | ( + | ObjectValueContainsCondition + | ObjectValueEqualsCondition + | ObjectValueGreaterThanCondition + | ObjectValueInRangeCondition + | ObjectValueIsSubsetOfCondition + | ObjectValueLessThanCondition + | ObjectValueMaxByCondition + | ObjectValueMinByCondition + | ObjectValueRelativeDateTimeCondition + )[] + | null; /** @format int32 */ skip?: number | null; /** @format int32 */ @@ -1750,16 +1750,16 @@ export interface DataRelevanceModifier { multiplyWeightBy: number; mustMatchAllConditions: boolean; conditions?: - | ( - | ContainsCondition - | DistinctCondition - | EqualsCondition - | GreaterThanCondition - | HasValueCondition - | LessThanCondition - | RelativeDateTimeCondition - )[] - | null; + | ( + | ContainsCondition + | DistinctCondition + | EqualsCondition + | GreaterThanCondition + | HasValueCondition + | LessThanCondition + | RelativeDateTimeCondition + )[] + | null; multiplierSelector?: DataDoubleSelector | FixedDoubleValueSelector | null; filters?: FilterCollection | null; custom?: Record; @@ -1767,18 +1767,18 @@ export interface DataRelevanceModifier { export interface DataValue { type: - | "String" - | "Double" - | "Boolean" - | "Multilingual" - | "Money" - | "MultiCurrency" - | "StringList" - | "DoubleList" - | "BooleanList" - | "MultilingualCollection" - | "Object" - | "ObjectList"; + | "String" + | "Double" + | "Boolean" + | "Multilingual" + | "Money" + | "MultiCurrency" + | "StringList" + | "DoubleList" + | "BooleanList" + | "MultilingualCollection" + | "Object" + | "ObjectList"; value?: any; isCollection: boolean; } @@ -2032,18 +2032,18 @@ export interface DisplayAdTemplateEntityStateGuidNullableDisplayAdTemplateMetada export interface DisplayAdTemplateFieldDefinition { name: string; type: - | "String" - | "Double" - | "Boolean" - | "Multilingual" - | "Money" - | "MultiCurrency" - | "StringList" - | "DoubleList" - | "BooleanList" - | "MultilingualCollection" - | "Object" - | "ObjectList"; + | "String" + | "Double" + | "Boolean" + | "Multilingual" + | "Money" + | "MultiCurrency" + | "StringList" + | "DoubleList" + | "BooleanList" + | "MultilingualCollection" + | "Object" + | "ObjectList"; metadata?: Record; } @@ -2526,84 +2526,84 @@ export interface Filter { export interface FilterCollection { items?: - | ( - | AndFilter - | BrandAssortmentFilter - | BrandDataFilter - | BrandDataHasKeyFilter - | BrandDisabledFilter - | BrandIdFilter - | CartDataFilter - | CompanyDataFilter - | CompanyDataHasKeyFilter - | CompanyDisabledFilter - | CompanyIdFilter - | ContentAssortmentFilter - | ContentCategoryAssortmentFilter - | ContentCategoryDataFilter - | ContentCategoryDataHasKeyFilter - | ContentCategoryDisabledFilter - | ContentCategoryHasAncestorFilter - | ContentCategoryHasChildFilter - | ContentCategoryHasContentsFilter - | ContentCategoryHasParentFilter - | ContentCategoryIdFilter - | ContentCategoryLevelFilter - | ContentCategoryRecentlyViewedByUserFilter - | ContentDataFilter - | ContentDataHasKeyFilter - | ContentDisabledFilter - | ContentEngagementFilter - | ContentHasCategoriesFilter - | ContentIdFilter - | ContentRecentlyViewedByUserFilter - | DisplayAdDataFilter - | DisplayAdIdFilter - | DisplayAdTemplateIdFilter - | OrFilter - | ProductAndVariantIdFilter - | ProductAssortmentFilter - | ProductCategoryAssortmentFilter - | ProductCategoryDataFilter - | ProductCategoryDataHasKeyFilter - | ProductCategoryDisabledFilter - | ProductCategoryHasAncestorFilter - | ProductCategoryHasChildFilter - | ProductCategoryHasParentFilter - | ProductCategoryHasProductsFilter - | ProductCategoryIdFilter - | ProductCategoryLevelFilter - | ProductCategoryRecentlyViewedByUserFilter - | ProductDataFilter - | ProductDataHasKeyFilter - | ProductDisabledFilter - | ProductDisplayNameFilter - | ProductEngagementFilter - | ProductHasCategoriesFilter - | ProductHasVariantsFilter - | ProductIdFilter - | ProductInCartFilter - | ProductListPriceFilter - | ProductRecentlyPurchasedByCompanyFilter - | ProductRecentlyPurchasedByUserCompanyFilter - | ProductRecentlyPurchasedByUserFilter - | ProductRecentlyPurchasedByUserParentCompanyFilter - | ProductRecentlyViewedByCompanyFilter - | ProductRecentlyViewedByUserCompanyFilter - | ProductRecentlyViewedByUserFilter - | ProductRecentlyViewedByUserParentCompanyFilter - | ProductSalesPriceFilter - | VariantAssortmentFilter - | VariantDataFilter - | VariantDataHasKeyFilter - | VariantDisabledFilter - | VariantEngagementFilter - | VariantIdFilter - | VariantListPriceFilter - | VariantSalesPriceFilter - | VariantSpecificationFilter - )[] - | null; + | ( + | AndFilter + | BrandAssortmentFilter + | BrandDataFilter + | BrandDataHasKeyFilter + | BrandDisabledFilter + | BrandIdFilter + | CartDataFilter + | CompanyDataFilter + | CompanyDataHasKeyFilter + | CompanyDisabledFilter + | CompanyIdFilter + | ContentAssortmentFilter + | ContentCategoryAssortmentFilter + | ContentCategoryDataFilter + | ContentCategoryDataHasKeyFilter + | ContentCategoryDisabledFilter + | ContentCategoryHasAncestorFilter + | ContentCategoryHasChildFilter + | ContentCategoryHasContentsFilter + | ContentCategoryHasParentFilter + | ContentCategoryIdFilter + | ContentCategoryLevelFilter + | ContentCategoryRecentlyViewedByUserFilter + | ContentDataFilter + | ContentDataHasKeyFilter + | ContentDisabledFilter + | ContentEngagementFilter + | ContentHasCategoriesFilter + | ContentIdFilter + | ContentRecentlyViewedByUserFilter + | DisplayAdDataFilter + | DisplayAdIdFilter + | DisplayAdTemplateIdFilter + | OrFilter + | ProductAndVariantIdFilter + | ProductAssortmentFilter + | ProductCategoryAssortmentFilter + | ProductCategoryDataFilter + | ProductCategoryDataHasKeyFilter + | ProductCategoryDisabledFilter + | ProductCategoryHasAncestorFilter + | ProductCategoryHasChildFilter + | ProductCategoryHasParentFilter + | ProductCategoryHasProductsFilter + | ProductCategoryIdFilter + | ProductCategoryLevelFilter + | ProductCategoryRecentlyViewedByUserFilter + | ProductDataFilter + | ProductDataHasKeyFilter + | ProductDisabledFilter + | ProductDisplayNameFilter + | ProductEngagementFilter + | ProductHasCategoriesFilter + | ProductHasVariantsFilter + | ProductIdFilter + | ProductInCartFilter + | ProductListPriceFilter + | ProductRecentlyPurchasedByCompanyFilter + | ProductRecentlyPurchasedByUserCompanyFilter + | ProductRecentlyPurchasedByUserFilter + | ProductRecentlyPurchasedByUserParentCompanyFilter + | ProductRecentlyViewedByCompanyFilter + | ProductRecentlyViewedByUserCompanyFilter + | ProductRecentlyViewedByUserFilter + | ProductRecentlyViewedByUserParentCompanyFilter + | ProductSalesPriceFilter + | VariantAssortmentFilter + | VariantDataFilter + | VariantDataHasKeyFilter + | VariantDisabledFilter + | VariantEngagementFilter + | VariantIdFilter + | VariantListPriceFilter + | VariantSalesPriceFilter + | VariantSpecificationFilter + )[] + | null; } export type FilterRule = MerchandisingRule; @@ -3154,16 +3154,16 @@ export interface MetadataValues { export type MixedRecommendationResponseCollection = TimedResponse & { responses?: - | ( - | BrandRecommendationResponse - | ContentCategoryRecommendationResponse - | ContentRecommendationResponse - | FeedRecommendationResponse - | ProductCategoryRecommendationResponse - | ProductRecommendationResponse - | SearchTermRecommendationResponse - )[] - | null; + | ( + | BrandRecommendationResponse + | ContentCategoryRecommendationResponse + | ContentRecommendationResponse + | FeedRecommendationResponse + | ProductCategoryRecommendationResponse + | ProductRecommendationResponse + | SearchTermRecommendationResponse + )[] + | null; }; export interface Money { @@ -3621,21 +3621,21 @@ export type ProductAdministrativeAction = Trackable & { filters: FilterCollection; language?: Language | null; productUpdateKind: - | "None" - | "DisableInRecommendations" - | "Disable" - | "EnableInRecommendations" - | "Enable" - | "PermanentlyDelete" - | "Delete"; + | "None" + | "DisableInRecommendations" + | "Disable" + | "EnableInRecommendations" + | "Enable" + | "PermanentlyDelete" + | "Delete"; variantUpdateKind: - | "None" - | "DisableInRecommendations" - | "Disable" - | "EnableInRecommendations" - | "Enable" - | "PermanentlyDelete" - | "Delete"; + | "None" + | "DisableInRecommendations" + | "Disable" + | "EnableInRecommendations" + | "Enable" + | "PermanentlyDelete" + | "Delete"; currency?: Currency | null; }; @@ -3776,45 +3776,45 @@ export type ProductCategoryFacetQuery = FacetQuery & { export interface ProductCategoryFacetResult { items?: - | ( - | ProductAssortmentFacetResult - | ContentAssortmentFacetResult - | ProductCategoryAssortmentFacetResult - | BrandFacetResult - | CategoryFacetResult - | CategoryHierarchyFacetResult - | ContentDataObjectFacetResult - | ContentDataDoubleRangeFacetResult - | ContentDataDoubleRangesFacetResult - | ContentDataStringValueFacetResult - | ContentDataBooleanValueFacetResult - | ContentDataDoubleValueFacetResult - | ContentDataIntegerValueFacetResult - | DataObjectFacetResult - | DataObjectDoubleRangeFacetResult - | DataObjectDoubleRangesFacetResult - | DataObjectStringValueFacetResult - | DataObjectBooleanValueFacetResult - | DataObjectDoubleValueFacetResult - | PriceRangeFacetResult - | PriceRangesFacetResult - | ProductCategoryDataObjectFacetResult - | ProductCategoryDataDoubleRangeFacetResult - | ProductCategoryDataDoubleRangesFacetResult - | ProductCategoryDataStringValueFacetResult - | ProductCategoryDataBooleanValueFacetResult - | ProductCategoryDataDoubleValueFacetResult - | ProductDataObjectFacetResult - | ProductDataDoubleRangeFacetResult - | ProductDataDoubleRangesFacetResult - | ProductDataStringValueFacetResult - | ProductDataBooleanValueFacetResult - | ProductDataDoubleValueFacetResult - | ProductDataIntegerValueFacetResult - | RecentlyPurchasedFacetResult - | VariantSpecificationFacetResult - )[] - | null; + | ( + | ProductAssortmentFacetResult + | ContentAssortmentFacetResult + | ProductCategoryAssortmentFacetResult + | BrandFacetResult + | CategoryFacetResult + | CategoryHierarchyFacetResult + | ContentDataObjectFacetResult + | ContentDataDoubleRangeFacetResult + | ContentDataDoubleRangesFacetResult + | ContentDataStringValueFacetResult + | ContentDataBooleanValueFacetResult + | ContentDataDoubleValueFacetResult + | ContentDataIntegerValueFacetResult + | DataObjectFacetResult + | DataObjectDoubleRangeFacetResult + | DataObjectDoubleRangesFacetResult + | DataObjectStringValueFacetResult + | DataObjectBooleanValueFacetResult + | DataObjectDoubleValueFacetResult + | PriceRangeFacetResult + | PriceRangesFacetResult + | ProductCategoryDataObjectFacetResult + | ProductCategoryDataDoubleRangeFacetResult + | ProductCategoryDataDoubleRangesFacetResult + | ProductCategoryDataStringValueFacetResult + | ProductCategoryDataBooleanValueFacetResult + | ProductCategoryDataDoubleValueFacetResult + | ProductDataObjectFacetResult + | ProductDataDoubleRangeFacetResult + | ProductDataDoubleRangesFacetResult + | ProductDataStringValueFacetResult + | ProductDataBooleanValueFacetResult + | ProductDataDoubleValueFacetResult + | ProductDataIntegerValueFacetResult + | RecentlyPurchasedFacetResult + | VariantSpecificationFacetResult + )[] + | null; } export type ProductCategoryHasAncestorFilter = HasAncestorCategoryFilter; @@ -3996,22 +3996,22 @@ export type ProductCategorySearchSettings = SearchSettings & { export interface ProductCategorySortBySpecification { value?: - | ProductCategoryAttributeSorting - | ProductCategoryDataSorting - | ProductCategoryPopularitySorting - | ProductCategoryRelevanceSorting - | null; + | ProductCategoryAttributeSorting + | ProductCategoryDataSorting + | ProductCategoryPopularitySorting + | ProductCategoryRelevanceSorting + | null; } export interface ProductCategorySorting { $type: string; order: "Ascending" | "Descending"; thenBy?: - | ProductCategoryAttributeSorting - | ProductCategoryDataSorting - | ProductCategoryPopularitySorting - | ProductCategoryRelevanceSorting - | null; + | ProductCategoryAttributeSorting + | ProductCategoryDataSorting + | ProductCategoryPopularitySorting + | ProductCategoryRelevanceSorting + | null; } export type ProductCategoryUpdate = CategoryUpdate & { @@ -4194,45 +4194,45 @@ export type ProductFacetQuery = FacetQuery & { export interface ProductFacetResult { items?: - | ( - | ProductAssortmentFacetResult - | ContentAssortmentFacetResult - | ProductCategoryAssortmentFacetResult - | BrandFacetResult - | CategoryFacetResult - | CategoryHierarchyFacetResult - | ContentDataObjectFacetResult - | ContentDataDoubleRangeFacetResult - | ContentDataDoubleRangesFacetResult - | ContentDataStringValueFacetResult - | ContentDataBooleanValueFacetResult - | ContentDataDoubleValueFacetResult - | ContentDataIntegerValueFacetResult - | DataObjectFacetResult - | DataObjectDoubleRangeFacetResult - | DataObjectDoubleRangesFacetResult - | DataObjectStringValueFacetResult - | DataObjectBooleanValueFacetResult - | DataObjectDoubleValueFacetResult - | PriceRangeFacetResult - | PriceRangesFacetResult - | ProductCategoryDataObjectFacetResult - | ProductCategoryDataDoubleRangeFacetResult - | ProductCategoryDataDoubleRangesFacetResult - | ProductCategoryDataStringValueFacetResult - | ProductCategoryDataBooleanValueFacetResult - | ProductCategoryDataDoubleValueFacetResult - | ProductDataObjectFacetResult - | ProductDataDoubleRangeFacetResult - | ProductDataDoubleRangesFacetResult - | ProductDataStringValueFacetResult - | ProductDataBooleanValueFacetResult - | ProductDataDoubleValueFacetResult - | ProductDataIntegerValueFacetResult - | RecentlyPurchasedFacetResult - | VariantSpecificationFacetResult - )[] - | null; + | ( + | ProductAssortmentFacetResult + | ContentAssortmentFacetResult + | ProductCategoryAssortmentFacetResult + | BrandFacetResult + | CategoryFacetResult + | CategoryHierarchyFacetResult + | ContentDataObjectFacetResult + | ContentDataDoubleRangeFacetResult + | ContentDataDoubleRangesFacetResult + | ContentDataStringValueFacetResult + | ContentDataBooleanValueFacetResult + | ContentDataDoubleValueFacetResult + | ContentDataIntegerValueFacetResult + | DataObjectFacetResult + | DataObjectDoubleRangeFacetResult + | DataObjectDoubleRangesFacetResult + | DataObjectStringValueFacetResult + | DataObjectBooleanValueFacetResult + | DataObjectDoubleValueFacetResult + | PriceRangeFacetResult + | PriceRangesFacetResult + | ProductCategoryDataObjectFacetResult + | ProductCategoryDataDoubleRangeFacetResult + | ProductCategoryDataDoubleRangesFacetResult + | ProductCategoryDataStringValueFacetResult + | ProductCategoryDataBooleanValueFacetResult + | ProductCategoryDataDoubleValueFacetResult + | ProductDataObjectFacetResult + | ProductDataDoubleRangeFacetResult + | ProductDataDoubleRangesFacetResult + | ProductDataStringValueFacetResult + | ProductDataBooleanValueFacetResult + | ProductDataDoubleValueFacetResult + | ProductDataIntegerValueFacetResult + | RecentlyPurchasedFacetResult + | VariantSpecificationFacetResult + )[] + | null; } export type ProductHasCategoriesFilter = Filter; @@ -4616,22 +4616,22 @@ export interface ProductRecommendationRequest { export type ProductRecommendationRequestCollection = LicensedRequest & { requests?: - | ( - | CustomProductRecommendationRequest - | PersonalProductRecommendationRequest - | PopularProductsRequest - | ProductsViewedAfterViewingContentRequest - | ProductsViewedAfterViewingProductRequest - | PurchasedWithCurrentCartRequest - | PurchasedWithMultipleProductsRequest - | PurchasedWithProductRequest - | RecentlyViewedProductsRequest - | SearchTermBasedProductRecommendationRequest - | SimilarProductsRequest - | SortProductsRequest - | SortVariantsRequest - )[] - | null; + | ( + | CustomProductRecommendationRequest + | PersonalProductRecommendationRequest + | PopularProductsRequest + | ProductsViewedAfterViewingContentRequest + | ProductsViewedAfterViewingProductRequest + | PurchasedWithCurrentCartRequest + | PurchasedWithMultipleProductsRequest + | PurchasedWithProductRequest + | RecentlyViewedProductsRequest + | SearchTermBasedProductRecommendationRequest + | SimilarProductsRequest + | SortProductsRequest + | SortVariantsRequest + )[] + | null; requireDistinctProductsAcrossResults: boolean; }; @@ -4772,28 +4772,28 @@ export type ProductSearchSettingsHighlightSettings = ProductProductHighlightProp export interface ProductSortBySpecification { value?: - | ProductAttributeSorting - | ProductDataObjectSorting - | ProductDataSorting - | ProductPopularitySorting - | ProductRelevanceSorting - | ProductVariantAttributeSorting - | ProductVariantSpecificationSorting - | null; + | ProductAttributeSorting + | ProductDataObjectSorting + | ProductDataSorting + | ProductPopularitySorting + | ProductRelevanceSorting + | ProductVariantAttributeSorting + | ProductVariantSpecificationSorting + | null; } export interface ProductSorting { $type: string; order: "Ascending" | "Descending"; thenBy?: - | ProductAttributeSorting - | ProductDataObjectSorting - | ProductDataSorting - | ProductPopularitySorting - | ProductRelevanceSorting - | ProductVariantAttributeSorting - | ProductVariantSpecificationSorting - | null; + | ProductAttributeSorting + | ProductDataObjectSorting + | ProductDataSorting + | ProductPopularitySorting + | ProductRelevanceSorting + | ProductVariantAttributeSorting + | ProductVariantSpecificationSorting + | null; } export type ProductUpdate = Trackable & { @@ -4880,7 +4880,6 @@ export interface PromotionSpecification { export interface PromotionSpecificationCollection { productPromotion?: ProductPromotionSpecification | null; - displayAdPromotion?: DisplayAdPromotionSpecification | null; } export interface PromotionSpecificationVariation { @@ -5090,39 +5089,39 @@ export interface RelevanceModifier { export interface RelevanceModifierCollection { items?: - | ( - | BrandIdRelevanceModifier - | ContentCategoryDataRelevanceModifier - | ContentCategoryRecentlyViewedByUserRelevanceModifier - | ContentDataRelevanceModifier - | ContentEngagementRelevanceModifier - | ContentRecentlyViewedByUserRelevanceModifier - | ProductAssortmentRelevanceModifier - | ProductCategoryDataRelevanceModifier - | ProductCategoryIdRelevanceModifier - | ProductCategoryRecentlyViewedByUserRelevanceModifier - | ProductDataRelevanceModifier - | ProductEngagementRelevanceModifier - | ProductIdRelevanceModifier - | ProductListPriceRelevanceModifier - | ProductRecentlyPurchasedByCompanyRelevanceModifier - | ProductRecentlyPurchasedByUserCompanyRelevanceModifier - | ProductRecentlyPurchasedByUserRelevanceModifier - | ProductRecentlyViewedByCompanyRelevanceModifier - | ProductRecentlyViewedByUserCompanyRelevanceModifier - | ProductRecentlyViewedByUserRelevanceModifier - | ProductSalesPriceRelevanceModifier - | UserFavoriteProductRelevanceModifier - | VariantAssortmentRelevanceModifier - | VariantDataRelevanceModifier - | VariantEngagementRelevanceModifier - | VariantIdRelevanceModifier - | VariantListPriceRelevanceModifier - | VariantSalesPriceRelevanceModifier - | VariantSpecificationsInCommonRelevanceModifier - | VariantSpecificationValueRelevanceModifier - )[] - | null; + | ( + | BrandIdRelevanceModifier + | ContentCategoryDataRelevanceModifier + | ContentCategoryRecentlyViewedByUserRelevanceModifier + | ContentDataRelevanceModifier + | ContentEngagementRelevanceModifier + | ContentRecentlyViewedByUserRelevanceModifier + | ProductAssortmentRelevanceModifier + | ProductCategoryDataRelevanceModifier + | ProductCategoryIdRelevanceModifier + | ProductCategoryRecentlyViewedByUserRelevanceModifier + | ProductDataRelevanceModifier + | ProductEngagementRelevanceModifier + | ProductIdRelevanceModifier + | ProductListPriceRelevanceModifier + | ProductRecentlyPurchasedByCompanyRelevanceModifier + | ProductRecentlyPurchasedByUserCompanyRelevanceModifier + | ProductRecentlyPurchasedByUserRelevanceModifier + | ProductRecentlyViewedByCompanyRelevanceModifier + | ProductRecentlyViewedByUserCompanyRelevanceModifier + | ProductRecentlyViewedByUserRelevanceModifier + | ProductSalesPriceRelevanceModifier + | UserFavoriteProductRelevanceModifier + | VariantAssortmentRelevanceModifier + | VariantDataRelevanceModifier + | VariantEngagementRelevanceModifier + | VariantIdRelevanceModifier + | VariantListPriceRelevanceModifier + | VariantSalesPriceRelevanceModifier + | VariantSpecificationsInCommonRelevanceModifier + | VariantSpecificationValueRelevanceModifier + )[] + | null; } export interface RequestConfiguration { @@ -5309,15 +5308,15 @@ export type SaveSynonymsResponse = TimedResponse & { export type SaveTriggerConfigurationRequest = LicensedRequest & { configuration?: - | AbandonedCartTriggerConfiguration - | AbandonedSearchTriggerConfiguration - | ContentCategoryInterestTriggerConfiguration - | ProductCategoryInterestTriggerConfiguration - | ProductChangeTriggerConfiguration - | ProductInterestTriggerConfiguration - | UserActivityTriggerConfiguration - | VariantChangeTriggerConfiguration - | null; + | AbandonedCartTriggerConfiguration + | AbandonedSearchTriggerConfiguration + | ContentCategoryInterestTriggerConfiguration + | ProductCategoryInterestTriggerConfiguration + | ProductChangeTriggerConfiguration + | ProductInterestTriggerConfiguration + | UserActivityTriggerConfiguration + | VariantChangeTriggerConfiguration + | null; modifiedBy?: string | null; }; @@ -5402,15 +5401,15 @@ export interface SearchResponse { export type SearchResponseCollection = SearchResponse & { responses?: - | ( - | ContentCategorySearchResponse - | ContentSearchResponse - | ProductCategorySearchResponse - | ProductSearchResponse - | SearchResponseCollection - | SearchTermPredictionResponse - )[] - | null; + | ( + | ContentCategorySearchResponse + | ContentSearchResponse + | ProductCategorySearchResponse + | ProductSearchResponse + | SearchResponseCollection + | SearchTermPredictionResponse + )[] + | null; }; export type SearchResultModifierRule = SearchRule & { @@ -6028,15 +6027,15 @@ export type SynonymsRequest = LicensedRequest & { export interface SynonymsRequestSynonymSortingSorting { sortBy: - | "Created" - | "CreatedBy" - | "Modified" - | "ModifiedBy" - | "Approved" - | "ApprovedBy" - | "Usages" - | "Type" - | "Predictable"; + | "Created" + | "CreatedBy" + | "Modified" + | "ModifiedBy" + | "Approved" + | "ApprovedBy" + | "Usages" + | "Type" + | "Predictable"; sortOrder: "Ascending" | "Descending"; } @@ -6174,17 +6173,17 @@ export interface TrackingRequest { export type TriggerConfigurationCollectionResponse = TimedResponse & { configurations?: - | ( - | AbandonedCartTriggerConfiguration - | AbandonedSearchTriggerConfiguration - | ContentCategoryInterestTriggerConfiguration - | ProductCategoryInterestTriggerConfiguration - | ProductChangeTriggerConfiguration - | ProductInterestTriggerConfiguration - | UserActivityTriggerConfiguration - | VariantChangeTriggerConfiguration - )[] - | null; + | ( + | AbandonedCartTriggerConfiguration + | AbandonedSearchTriggerConfiguration + | ContentCategoryInterestTriggerConfiguration + | ProductCategoryInterestTriggerConfiguration + | ProductChangeTriggerConfiguration + | ProductInterestTriggerConfiguration + | UserActivityTriggerConfiguration + | VariantChangeTriggerConfiguration + )[] + | null; }; export type TriggerConfigurationRequest = LicensedRequest & { @@ -6196,15 +6195,15 @@ export type TriggerConfigurationRequest = LicensedRequest & { export type TriggerConfigurationResponse = TimedResponse & { configuration?: - | AbandonedCartTriggerConfiguration - | AbandonedSearchTriggerConfiguration - | ContentCategoryInterestTriggerConfiguration - | ProductCategoryInterestTriggerConfiguration - | ProductChangeTriggerConfiguration - | ProductInterestTriggerConfiguration - | UserActivityTriggerConfiguration - | VariantChangeTriggerConfiguration - | null; + | AbandonedCartTriggerConfiguration + | AbandonedSearchTriggerConfiguration + | ContentCategoryInterestTriggerConfiguration + | ProductCategoryInterestTriggerConfiguration + | ProductChangeTriggerConfiguration + | ProductInterestTriggerConfiguration + | UserActivityTriggerConfiguration + | VariantChangeTriggerConfiguration + | null; }; export type TriggerConfigurationsRequest = LicensedRequest & { @@ -6279,23 +6278,23 @@ export interface UserCondition { export interface UserConditionCollection { items?: - | ( - | AndCondition - | HasActivityCondition - | HasAuthenticatedIdCondition - | HasClassificationCondition - | HasCompanyDataCondition - | HasDataCondition - | HasEmailCondition - | HasIdentifierCondition - | HasLineItemsInCartCondition - | HasModifiedCartCondition - | HasPlacedOrderCondition - | HasRecentlyReceivedSameTriggerCondition - | HasRecentlyReceivedTriggerCondition - | OrCondition - )[] - | null; + | ( + | AndCondition + | HasActivityCondition + | HasAuthenticatedIdCondition + | HasClassificationCondition + | HasCompanyDataCondition + | HasDataCondition + | HasEmailCondition + | HasIdentifierCondition + | HasLineItemsInCartCondition + | HasModifiedCartCondition + | HasPlacedOrderCondition + | HasRecentlyReceivedSameTriggerCondition + | HasRecentlyReceivedTriggerCondition + | OrCondition + )[] + | null; } export interface UserConditionConfiguration { @@ -6378,16 +6377,16 @@ export interface ValueCondition { export interface ValueConditionCollection { items?: - | ( - | ContainsCondition - | DistinctCondition - | EqualsCondition - | GreaterThanCondition - | HasValueCondition - | LessThanCondition - | RelativeDateTimeCondition - )[] - | null; + | ( + | ContainsCondition + | DistinctCondition + | EqualsCondition + | GreaterThanCondition + | HasValueCondition + | LessThanCondition + | RelativeDateTimeCondition + )[] + | null; } export interface ValueSelector { From 474b9e13e07965216fade3a97b18524fc46dae2e Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Thu, 6 Nov 2025 10:53:08 +0100 Subject: [PATCH 13/14] tweaks --- ...feedRecommendationInitializationBuilder.ts | 24 ++++--------------- .../feedRecommendations.integration.test.ts | 14 +++++++---- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts index 41c94b64..ae11f0a0 100644 --- a/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts +++ b/packages/client/src/builders/recommendation/feed/feedRecommendationInitializationBuilder.ts @@ -6,7 +6,7 @@ import { FeedCompositionBuilder, FeedCompositionOptions } from './feedCompositio export class FeedRecommendationInitializationBuilder extends RecommendationRequestBuilder { private feed: Feed; - constructor({ minimumPageSize }: { minimumPageSize: number }, settings: Settings) { + constructor(settings: Settings, { minimumPageSize }: { minimumPageSize: number }) { super(settings); this.feed = { @@ -28,30 +28,16 @@ export class FeedRecommendationInitializationBuilder extends RecommendationReque } /** - * Defines how the feed will be composed, which types of entities to include, how many of each type, and any filters or relevance modifiers that should apply to each type, etc. - * @param compositions - */ - public addCompositions(compositions: FeedComposition[]): this { - this.feed.compositions ??= []; - for (const composition of compositions) { - this.feed.compositions.push(composition); - } - - return this; - } - - /** - * Adds a composition to the feed. + * Adds a composition to the feed. Defines how the feed will be composed, which types of entities to include, how many of each type, and any filters or relevance modifiers that should apply to each type, etc. * @param options * @param builderFn - * @returns */ - public addCompostion(options: FeedCompositionOptions, builderFn?: (feedBuilder: FeedCompositionBuilder) => void): this { + public addCompostion({ options, settingsBuilder }: { options: FeedCompositionOptions, settingsBuilder?: (feedBuilder: FeedCompositionBuilder) => void }): this { this.feed.compositions ??= []; const builder = new FeedCompositionBuilder(options); - if (builderFn) { - builderFn(builder); + if (settingsBuilder) { + settingsBuilder(builder); } this.feed.compositions.push(builder.build()); diff --git a/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts b/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts index d24c9b6d..ad38e324 100644 --- a/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts +++ b/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts @@ -14,12 +14,16 @@ const settings = { test('Feed Recommendation', async () => { - const request = new FeedRecommendationInitializationBuilder({ minimumPageSize: 10 }, settings) + const request = new FeedRecommendationInitializationBuilder(settings, { minimumPageSize: 10 }) .addCompostion({ - type: 'Product', - count: { lowerBoundInclusive: 1, upperBoundInclusive: 2 } - } - ); + options: { + type: 'Product', + count: { lowerBoundInclusive: 1, upperBoundInclusive: 2 } + }, + settingsBuilder: (builder) => { + builder.rotationLimit(5) + } + }); const result = await recommender.recommendFeedRecommendationInitialization(request.build()); From af8e3814df4744db3a07b9accb7d7aeeccc8d8f0 Mon Sep 17 00:00:00 2001 From: Martin Zanoni Date: Fri, 7 Nov 2025 07:36:59 +0100 Subject: [PATCH 14/14] review re-name --- packages/client/src/recommender.ts | 4 ++-- .../integration-tests/feedRecommendations.integration.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/src/recommender.ts b/packages/client/src/recommender.ts index b457f227..7a01c024 100644 --- a/packages/client/src/recommender.ts +++ b/packages/client/src/recommender.ts @@ -167,11 +167,11 @@ export class Recommender extends RelewiseClient { //#endregion //#region feed - public async recommendFeedRecommendationInitialization(request: FeedRecommendationInitializationRequest, options?: RelewiseRequestOptions): Promise { + public async recommendFeedInitialization(request: FeedRecommendationInitializationRequest, options?: RelewiseRequestOptions): Promise { return this.request('FeedRecommendationInitializationRequest', request, options); } - public async recommendFeedRecommendationNextItems(request: FeedRecommendationNextItemsRequest, options?: RelewiseRequestOptions): Promise { + public async recommendFeedNextItems(request: FeedRecommendationNextItemsRequest, options?: RelewiseRequestOptions): Promise { return this.request('FeedRecommendationNextItemsRequest', request, options); } //#endregion diff --git a/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts b/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts index ad38e324..0294dc22 100644 --- a/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts +++ b/packages/client/tests/integration-tests/feedRecommendations.integration.test.ts @@ -25,7 +25,7 @@ test('Feed Recommendation', async () => { } }); - const result = await recommender.recommendFeedRecommendationInitialization(request.build()); + const result = await recommender.recommendFeedInitialization(request.build()); expect(result).not.toBe(undefined); }); \ No newline at end of file