@reactionary/algolia 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/capabilities/analytics.capability.js +13 -4
- package/capabilities/product-recommendations.capability.js +11 -6
- package/capabilities/product-search.capability.js +7 -1
- package/package.json +2 -2
- package/src/capabilities/analytics.capability.d.ts +1 -0
- package/src/capabilities/product-recommendations.capability.d.ts +2 -2
- package/src/capabilities/product-search.capability.d.ts +4 -2
|
@@ -5,13 +5,18 @@ import {
|
|
|
5
5
|
algoliasearch
|
|
6
6
|
} from "algoliasearch";
|
|
7
7
|
import { getProductIndexNameForLocale } from "../core/index-utils.js";
|
|
8
|
+
import { hash } from "node:crypto";
|
|
8
9
|
class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
9
10
|
client;
|
|
10
11
|
config;
|
|
12
|
+
authenticatedUserToken = void 0;
|
|
11
13
|
constructor(cache, requestContext, config) {
|
|
12
14
|
super(cache, requestContext);
|
|
13
15
|
this.config = config;
|
|
14
16
|
this.client = algoliasearch(this.config.appId, this.config.apiKey).initInsights({});
|
|
17
|
+
if (requestContext.session.identityContext.identity.type === "Registered") {
|
|
18
|
+
this.authenticatedUserToken = hash("sha256", requestContext.session.identityContext.identity.id.userId);
|
|
19
|
+
}
|
|
15
20
|
}
|
|
16
21
|
async processProductAddToCart(event) {
|
|
17
22
|
if (event.source && event.source.type === "search") {
|
|
@@ -21,7 +26,8 @@ class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
|
21
26
|
eventSubtype: "addToCart",
|
|
22
27
|
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
23
28
|
objectIDs: [event.product.key],
|
|
24
|
-
userToken:
|
|
29
|
+
userToken: event.personalizationProfile?.identifier.key || "anonymous",
|
|
30
|
+
authenticatedUserToken: this.authenticatedUserToken,
|
|
25
31
|
queryID: event.source.identifier.key
|
|
26
32
|
};
|
|
27
33
|
await this.client.pushEvents({
|
|
@@ -36,7 +42,8 @@ class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
|
36
42
|
eventType: "click",
|
|
37
43
|
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
38
44
|
objectIDs: [event.product.key],
|
|
39
|
-
userToken:
|
|
45
|
+
userToken: event.personalizationProfile?.identifier.key || "anonymous",
|
|
46
|
+
authenticatedUserToken: this.authenticatedUserToken,
|
|
40
47
|
positions: [event.position],
|
|
41
48
|
queryID: event.source.identifier.key
|
|
42
49
|
};
|
|
@@ -52,7 +59,8 @@ class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
|
52
59
|
eventType: "view",
|
|
53
60
|
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
54
61
|
objectIDs: event.products.map((x) => x.key),
|
|
55
|
-
userToken:
|
|
62
|
+
userToken: event.personalizationProfile?.identifier.key || "anonymous",
|
|
63
|
+
authenticatedUserToken: this.authenticatedUserToken
|
|
56
64
|
};
|
|
57
65
|
await this.client.pushEvents({
|
|
58
66
|
events: [algoliaEvent]
|
|
@@ -66,7 +74,8 @@ class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
|
66
74
|
eventSubtype: "purchase",
|
|
67
75
|
index: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
68
76
|
objectIDs: event.order.items.map((x) => x.variant.sku),
|
|
69
|
-
userToken:
|
|
77
|
+
userToken: event.personalizationProfile?.identifier.key || "anonymous",
|
|
78
|
+
authenticatedUserToken: this.authenticatedUserToken
|
|
70
79
|
};
|
|
71
80
|
await this.client.pushEvents({
|
|
72
81
|
events: [algoliaEvent]
|
|
@@ -19,11 +19,16 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
19
19
|
getRecommendationThreshold(_algorithm) {
|
|
20
20
|
return 10;
|
|
21
21
|
}
|
|
22
|
-
getQueryParametersForRecommendations(algorithm) {
|
|
22
|
+
getQueryParametersForRecommendations(algorithm, query) {
|
|
23
|
+
const ruleContexts = query.personalizationProfile ? [...query.personalizationProfile.segments.map((segment) => "segment:" + segment)] : [];
|
|
24
|
+
if (query.labels) {
|
|
25
|
+
ruleContexts.push(...query.labels);
|
|
26
|
+
}
|
|
23
27
|
return {
|
|
24
|
-
userToken:
|
|
28
|
+
userToken: query.personalizationProfile?.identifier.key || "anonymous",
|
|
25
29
|
analytics: true,
|
|
26
30
|
analyticsTags: ["reactionary", algorithm],
|
|
31
|
+
ruleContexts,
|
|
27
32
|
clickAnalytics: true
|
|
28
33
|
};
|
|
29
34
|
}
|
|
@@ -44,7 +49,7 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
44
49
|
objectID: query.sourceProduct.key,
|
|
45
50
|
maxRecommendations: query.numberOfRecommendations,
|
|
46
51
|
threshold: this.getRecommendationThreshold("bought-together"),
|
|
47
|
-
queryParameters: this.getQueryParametersForRecommendations("bought-together")
|
|
52
|
+
queryParameters: this.getQueryParametersForRecommendations("bought-together", query)
|
|
48
53
|
}
|
|
49
54
|
]
|
|
50
55
|
});
|
|
@@ -77,7 +82,7 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
77
82
|
objectID: query.sourceProduct.key,
|
|
78
83
|
maxRecommendations: query.numberOfRecommendations,
|
|
79
84
|
threshold: this.getRecommendationThreshold("looking-similar"),
|
|
80
|
-
queryParameters: this.getQueryParametersForRecommendations("looking-similar")
|
|
85
|
+
queryParameters: this.getQueryParametersForRecommendations("looking-similar", query)
|
|
81
86
|
}
|
|
82
87
|
]
|
|
83
88
|
});
|
|
@@ -110,7 +115,7 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
110
115
|
objectID: query.sourceProduct.key,
|
|
111
116
|
maxRecommendations: query.numberOfRecommendations,
|
|
112
117
|
threshold: this.getRecommendationThreshold("related-products"),
|
|
113
|
-
queryParameters: this.getQueryParametersForRecommendations("related-products")
|
|
118
|
+
queryParameters: this.getQueryParametersForRecommendations("related-products", query)
|
|
114
119
|
}
|
|
115
120
|
]
|
|
116
121
|
});
|
|
@@ -144,7 +149,7 @@ class AlgoliaProductRecommendationsCapability extends ProductRecommendationsCapa
|
|
|
144
149
|
facetValue: query.sourceCategory.key,
|
|
145
150
|
maxRecommendations: query.numberOfRecommendations,
|
|
146
151
|
threshold: this.getRecommendationThreshold("trending-items"),
|
|
147
|
-
queryParameters: this.getQueryParametersForRecommendations("trending-items")
|
|
152
|
+
queryParameters: this.getQueryParametersForRecommendations("trending-items", query)
|
|
148
153
|
}
|
|
149
154
|
]
|
|
150
155
|
});
|
|
@@ -40,6 +40,10 @@ class AlgoliaProductSearchCapability extends ProductSearchCapability {
|
|
|
40
40
|
if (categoryFacet) {
|
|
41
41
|
finalFilters.push(`categories:"${categoryFacet.key}"`);
|
|
42
42
|
}
|
|
43
|
+
const rulesContext = [];
|
|
44
|
+
if (payload.personalizationProfile) {
|
|
45
|
+
rulesContext.push(...payload.personalizationProfile.segments.map((s) => `segment:${s}`));
|
|
46
|
+
}
|
|
43
47
|
return {
|
|
44
48
|
indexName: getProductIndexNameForLocale(this.config.indexName, this.context.languageContext.locale),
|
|
45
49
|
query: payload.search.term,
|
|
@@ -49,7 +53,9 @@ class AlgoliaProductSearchCapability extends ProductSearchCapability {
|
|
|
49
53
|
analytics: true,
|
|
50
54
|
clickAnalytics: true,
|
|
51
55
|
facetFilters: finalFacetFilters,
|
|
52
|
-
filters: finalFilters.join(" AND ")
|
|
56
|
+
filters: finalFilters.join(" AND "),
|
|
57
|
+
ruleContexts: rulesContext,
|
|
58
|
+
userToken: payload.personalizationProfile?.identifier.key || "anonymous"
|
|
53
59
|
};
|
|
54
60
|
}
|
|
55
61
|
async queryByTerm(payload) {
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/algolia",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@reactionary/core": "0.
|
|
8
|
+
"@reactionary/core": "0.9.1",
|
|
9
9
|
"zod": "4.1.9",
|
|
10
10
|
"algoliasearch": "^5.48.0",
|
|
11
11
|
"vitest": "^4.0.9",
|
|
@@ -4,6 +4,7 @@ import type { AlgoliaConfiguration } from '../schema/configuration.schema.js';
|
|
|
4
4
|
export declare class AlgoliaAnalyticsCapability extends AnalyticsCapability {
|
|
5
5
|
protected client: InsightsClient;
|
|
6
6
|
protected config: AlgoliaConfiguration;
|
|
7
|
+
protected authenticatedUserToken: string | undefined;
|
|
7
8
|
constructor(cache: Cache, requestContext: RequestContext, config: AlgoliaConfiguration);
|
|
8
9
|
protected processProductAddToCart(event: AnalyticsMutationProductAddToCartEvent): Promise<void>;
|
|
9
10
|
protected processProductSummaryClick(event: AnalyticsMutationProductSummaryClickEvent): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Cache, ProductRecommendationsCapability, type ProductRecommendation, type ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuery, type ProductRecommendationAlgorithmSimilarProductsQuery, type ProductRecommendationAlgorithmRelatedProductsQuery, type ProductRecommendationAlgorithmTrendingInCategoryQuery, type RequestContext, type ProductRecommendationsQuery, type ProductSearchResultItemVariant } from '@reactionary/core';
|
|
1
|
+
import { type Cache, ProductRecommendationsCapability, type ProductRecommendation, type ProductRecommendationAlgorithmFrequentlyBoughtTogetherQuery, type ProductRecommendationAlgorithmSimilarProductsQuery, type ProductRecommendationAlgorithmRelatedProductsQuery, type ProductRecommendationAlgorithmTrendingInCategoryQuery, type RequestContext, type ProductRecommendationsQuery, type ProductSearchResultItemVariant, type ProductRecommendationBaseQuery } from '@reactionary/core';
|
|
2
2
|
import { type RecommendationsResults, type RecommendSearchParams, type LiteClient } from 'algoliasearch/lite';
|
|
3
3
|
import type { AlgoliaConfiguration } from '../schema/configuration.schema.js';
|
|
4
4
|
import type { AlgoliaProductRecommendationIdentifier } from '../schema/product-recommendation.schema.js';
|
|
@@ -17,7 +17,7 @@ export declare class AlgoliaProductRecommendationsCapability extends ProductReco
|
|
|
17
17
|
protected client: LiteClient;
|
|
18
18
|
constructor(config: AlgoliaConfiguration, cache: Cache, context: RequestContext);
|
|
19
19
|
protected getRecommendationThreshold(_algorithm: string): number;
|
|
20
|
-
protected getQueryParametersForRecommendations(algorithm: string): RecommendSearchParams;
|
|
20
|
+
protected getQueryParametersForRecommendations(algorithm: string, query: ProductRecommendationBaseQuery): RecommendSearchParams;
|
|
21
21
|
/**
|
|
22
22
|
* Get frequently bought together recommendations using Algolia Recommend
|
|
23
23
|
*/
|
|
@@ -11,10 +11,12 @@ export declare class AlgoliaProductSearchCapability<TFactory extends ProductSear
|
|
|
11
11
|
page: number;
|
|
12
12
|
hitsPerPage: number;
|
|
13
13
|
facets: string[];
|
|
14
|
-
analytics:
|
|
15
|
-
clickAnalytics:
|
|
14
|
+
analytics: true;
|
|
15
|
+
clickAnalytics: true;
|
|
16
16
|
facetFilters: string[];
|
|
17
17
|
filters: string;
|
|
18
|
+
ruleContexts: string[];
|
|
19
|
+
userToken: string;
|
|
18
20
|
};
|
|
19
21
|
queryByTerm(payload: ProductSearchQueryByTerm): Promise<Result<ProductSearchFactoryOutput<TFactory>>>;
|
|
20
22
|
createCategoryNavigationFilter(payload: ProductSearchQueryCreateNavigationFilter): Promise<Result<FacetValueIdentifier>>;
|