@reactionary/core 0.11.2 → 0.12.0
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/analytics/context.js +173 -0
- package/analytics/dispatcher.js +181 -0
- package/analytics/index.js +6 -0
- package/analytics/legacy-adapter.js +48 -0
- package/analytics/origins.js +64 -0
- package/analytics/recording-subscriber.js +26 -0
- package/analytics/refs.js +14 -0
- package/capabilities/analytics.capability.js +265 -84
- package/capabilities/analytics.provider.js +13 -0
- package/capabilities/index.js +1 -0
- package/client/client-builder.js +45 -16
- package/index.js +1 -0
- package/package.json +1 -1
- package/schemas/models/analytics/consent.model.js +10 -0
- package/schemas/models/analytics/dispatch.model.js +15 -0
- package/schemas/models/analytics/envelope.model.js +38 -0
- package/schemas/models/analytics/event-parts.model.js +47 -0
- package/schemas/models/analytics/event.model.js +255 -0
- package/schemas/models/analytics/index.js +6 -0
- package/schemas/models/analytics/origin.model.js +113 -0
- package/schemas/models/analytics.model.js +0 -2
- package/schemas/models/index.js +1 -0
- package/schemas/mutations/analytics/events/account.mutation.js +66 -0
- package/schemas/mutations/analytics/events/base.mutation.js +10 -0
- package/schemas/mutations/analytics/events/browse.mutation.js +53 -0
- package/schemas/mutations/analytics/events/commerce.mutation.js +79 -0
- package/schemas/mutations/analytics/events/index.js +85 -0
- package/schemas/mutations/analytics/index.js +1 -0
- package/schemas/session.schema.js +3 -1
- package/src/analytics/context.d.ts +85 -0
- package/src/analytics/dispatcher.d.ts +71 -0
- package/src/analytics/index.d.ts +6 -0
- package/src/analytics/legacy-adapter.d.ts +10 -0
- package/src/analytics/origins.d.ts +25 -0
- package/src/analytics/recording-subscriber.d.ts +18 -0
- package/src/analytics/refs.d.ts +8 -0
- package/src/capabilities/analytics.capability.d.ts +64 -17
- package/src/capabilities/analytics.provider.d.ts +24 -0
- package/src/capabilities/index.d.ts +1 -0
- package/src/client/client-builder.d.ts +25 -2
- package/src/index.d.ts +1 -0
- package/src/schemas/capabilities.schema.d.ts +8 -1
- package/src/schemas/models/analytics/consent.model.d.ts +13 -0
- package/src/schemas/models/analytics/dispatch.model.d.ts +29 -0
- package/src/schemas/models/analytics/envelope.model.d.ts +565 -0
- package/src/schemas/models/analytics/event-parts.model.d.ts +248 -0
- package/src/schemas/models/analytics/event.model.d.ts +83182 -0
- package/src/schemas/models/analytics/index.d.ts +6 -0
- package/src/schemas/models/analytics/origin.model.d.ts +275 -0
- package/src/schemas/models/analytics.model.d.ts +1 -2
- package/src/schemas/models/index.d.ts +1 -0
- package/src/schemas/mutations/analytics/events/account.mutation.d.ts +1939 -0
- package/src/schemas/mutations/analytics/events/base.mutation.d.ts +121 -0
- package/src/schemas/mutations/analytics/events/browse.mutation.d.ts +1832 -0
- package/src/schemas/mutations/analytics/events/commerce.mutation.d.ts +30188 -0
- package/src/schemas/mutations/analytics/events/index.d.ts +33928 -0
- package/src/schemas/mutations/analytics/index.d.ts +1 -0
- package/src/schemas/mutations/checkout.mutation.d.ts +4 -4
- package/src/schemas/mutations/product-list.mutation.d.ts +2 -2
- package/src/schemas/session.schema.d.ts +8 -0
|
@@ -8,102 +8,283 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
8
8
|
if (kind && result) __defProp(target, key, result);
|
|
9
9
|
return result;
|
|
10
10
|
};
|
|
11
|
-
import {
|
|
11
|
+
import { emitLegacyAnalyticsEvent } from "../analytics/legacy-adapter.js";
|
|
12
|
+
import { Reactionary } from "../decorators/reactionary.decorator.js";
|
|
12
13
|
import {
|
|
14
|
+
AnalyticsEventResultSchema,
|
|
13
15
|
AnalyticsMutationSchema,
|
|
14
|
-
AnalyticsResultSchema
|
|
16
|
+
AnalyticsResultSchema,
|
|
17
|
+
AnalyticsMutationPageViewedSchema,
|
|
18
|
+
AnalyticsMutationSearchResultsViewedSchema,
|
|
19
|
+
AnalyticsMutationAutocompleteSuggestionSelectedSchema,
|
|
20
|
+
AnalyticsMutationCategoryViewedSchema,
|
|
21
|
+
AnalyticsMutationProductCarouselViewedSchema,
|
|
22
|
+
AnalyticsMutationProductClickedSchema,
|
|
23
|
+
AnalyticsMutationProductViewedSchema,
|
|
24
|
+
AnalyticsMutationPromotionViewedSchema,
|
|
25
|
+
AnalyticsMutationPromotionClickedSchema,
|
|
26
|
+
AnalyticsMutationCartItemAddedSchema,
|
|
27
|
+
AnalyticsMutationCartItemRemovedSchema,
|
|
28
|
+
AnalyticsMutationCartItemQuantityChangedSchema,
|
|
29
|
+
AnalyticsMutationCartViewedSchema,
|
|
30
|
+
AnalyticsMutationCouponAppliedSchema,
|
|
31
|
+
AnalyticsMutationCouponRejectedSchema,
|
|
32
|
+
AnalyticsMutationCheckoutStartedSchema,
|
|
33
|
+
AnalyticsMutationShippingInfoAddedSchema,
|
|
34
|
+
AnalyticsMutationPaymentInfoAddedSchema,
|
|
35
|
+
AnalyticsMutationOrderPlacedSchema,
|
|
36
|
+
AnalyticsMutationQuoteRequestedSchema,
|
|
37
|
+
AnalyticsMutationOrderReorderedSchema,
|
|
38
|
+
AnalyticsMutationCompanyRegisteredSchema,
|
|
39
|
+
AnalyticsMutationUserLoggedInSchema,
|
|
40
|
+
AnalyticsMutationUserLoggedOutSchema,
|
|
41
|
+
AnalyticsMutationUserRegisteredSchema,
|
|
42
|
+
AnalyticsMutationProfileUpdatedSchema,
|
|
43
|
+
AnalyticsMutationConsentChangedSchema,
|
|
44
|
+
AnalyticsMutationNewsletterSubscribedSchema,
|
|
45
|
+
AnalyticsMutationWishlistItemAddedSchema,
|
|
46
|
+
AnalyticsMutationWishlistItemRemovedSchema,
|
|
47
|
+
AnalyticsMutationBackInStockRequestedSchema,
|
|
48
|
+
AnalyticsMutationReviewSubmittedSchema,
|
|
49
|
+
AnalyticsMutationStoreSelectedSchema,
|
|
50
|
+
AnalyticsMutationProductSharedSchema,
|
|
51
|
+
AnalyticsMutationCustomSchema
|
|
15
52
|
} from "../schemas/index.js";
|
|
16
|
-
import {
|
|
53
|
+
import { BaseCapability } from "./base.capability.js";
|
|
17
54
|
class AnalyticsCapability extends BaseCapability {
|
|
55
|
+
dispatcher;
|
|
56
|
+
constructor(cache, context, dispatcher) {
|
|
57
|
+
super(cache, context);
|
|
58
|
+
this.dispatcher = dispatcher;
|
|
59
|
+
}
|
|
18
60
|
getResourceName() {
|
|
19
61
|
return "analytics";
|
|
20
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Delivers everything queued so far and resolves once delivery is done. For scripts, tests and
|
|
65
|
+
* runtimes without `waitUntil`. Never rejects.
|
|
66
|
+
*/
|
|
67
|
+
async flush() {
|
|
68
|
+
await this.dispatcher.flush();
|
|
69
|
+
}
|
|
21
70
|
async track(event) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return this.processProductSummaryView(event);
|
|
25
|
-
case "product-summary-click":
|
|
26
|
-
return this.processProductSummaryClick(event);
|
|
27
|
-
case "product-details-view":
|
|
28
|
-
return this.processProductDetailsView(event);
|
|
29
|
-
case "product-cart-add":
|
|
30
|
-
return this.processProductAddToCart(event);
|
|
31
|
-
case "purchase":
|
|
32
|
-
return this.processPurchase(event);
|
|
33
|
-
default:
|
|
34
|
-
return this.ignored();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
async processProductSummaryView(_event) {
|
|
38
|
-
return this.ignored();
|
|
39
|
-
}
|
|
40
|
-
async processProductSummaryClick(_event) {
|
|
41
|
-
return this.ignored();
|
|
42
|
-
}
|
|
43
|
-
async processProductDetailsView(_event) {
|
|
44
|
-
return this.ignored();
|
|
45
|
-
}
|
|
46
|
-
async processProductAddToCart(_event) {
|
|
47
|
-
return this.ignored();
|
|
48
|
-
}
|
|
49
|
-
async processPurchase(_event) {
|
|
50
|
-
return this.ignored();
|
|
51
|
-
}
|
|
52
|
-
accepted() {
|
|
53
|
-
return {
|
|
54
|
-
outcomes: [
|
|
55
|
-
{
|
|
56
|
-
provider: this.getResourceName(),
|
|
57
|
-
outcome: "accepted"
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
ignored() {
|
|
63
|
-
return {
|
|
64
|
-
outcomes: [
|
|
65
|
-
{
|
|
66
|
-
provider: this.getResourceName(),
|
|
67
|
-
outcome: "ignored"
|
|
68
|
-
}
|
|
69
|
-
]
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
rejected() {
|
|
73
|
-
return {
|
|
74
|
-
outcomes: [
|
|
75
|
-
{
|
|
76
|
-
provider: this.getResourceName(),
|
|
77
|
-
outcome: "rejected"
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
};
|
|
71
|
+
const result = await emitLegacyAnalyticsEvent(event, this.dispatcher);
|
|
72
|
+
return { outcomes: [{ provider: this.getResourceName(), outcome: result.success ? "accepted" : "rejected" }] };
|
|
81
73
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
capabilities;
|
|
85
|
-
constructor(cache, requestContext, capabilities) {
|
|
86
|
-
super(cache, requestContext);
|
|
87
|
-
this.capabilities = capabilities;
|
|
74
|
+
async pageViewed(payload) {
|
|
75
|
+
return this.dispatcher.emit("page-viewed", payload);
|
|
88
76
|
}
|
|
89
|
-
async
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
77
|
+
async searchResultsViewed(payload) {
|
|
78
|
+
return this.dispatcher.emit("search-results-viewed", payload);
|
|
79
|
+
}
|
|
80
|
+
async autocompleteSuggestionSelected(payload) {
|
|
81
|
+
return this.dispatcher.emit("autocomplete-suggestion-selected", payload);
|
|
82
|
+
}
|
|
83
|
+
async categoryViewed(payload) {
|
|
84
|
+
return this.dispatcher.emit("category-viewed", payload);
|
|
85
|
+
}
|
|
86
|
+
async productCarouselViewed(payload) {
|
|
87
|
+
return this.dispatcher.emit("product-carousel-viewed", payload);
|
|
88
|
+
}
|
|
89
|
+
async productClicked(payload) {
|
|
90
|
+
return this.dispatcher.emit("product-clicked", payload);
|
|
91
|
+
}
|
|
92
|
+
async productViewed(payload) {
|
|
93
|
+
return this.dispatcher.emit("product-viewed", payload);
|
|
94
|
+
}
|
|
95
|
+
async promotionViewed(payload) {
|
|
96
|
+
return this.dispatcher.emit("promotion-viewed", payload);
|
|
97
|
+
}
|
|
98
|
+
async promotionClicked(payload) {
|
|
99
|
+
return this.dispatcher.emit("promotion-clicked", payload);
|
|
100
|
+
}
|
|
101
|
+
async cartItemAdded(payload) {
|
|
102
|
+
return this.dispatcher.emit("cart-item-added", payload);
|
|
103
|
+
}
|
|
104
|
+
async cartItemRemoved(payload) {
|
|
105
|
+
return this.dispatcher.emit("cart-item-removed", payload);
|
|
106
|
+
}
|
|
107
|
+
async cartItemQuantityChanged(payload) {
|
|
108
|
+
return this.dispatcher.emit("cart-item-quantity-changed", payload);
|
|
109
|
+
}
|
|
110
|
+
async cartViewed(payload) {
|
|
111
|
+
return this.dispatcher.emit("cart-viewed", payload);
|
|
112
|
+
}
|
|
113
|
+
async couponApplied(payload) {
|
|
114
|
+
return this.dispatcher.emit("coupon-applied", payload);
|
|
115
|
+
}
|
|
116
|
+
async couponRejected(payload) {
|
|
117
|
+
return this.dispatcher.emit("coupon-rejected", payload);
|
|
118
|
+
}
|
|
119
|
+
async checkoutStarted(payload) {
|
|
120
|
+
return this.dispatcher.emit("checkout-started", payload);
|
|
121
|
+
}
|
|
122
|
+
async shippingInfoAdded(payload) {
|
|
123
|
+
return this.dispatcher.emit("shipping-info-added", payload);
|
|
124
|
+
}
|
|
125
|
+
async paymentInfoAdded(payload) {
|
|
126
|
+
return this.dispatcher.emit("payment-info-added", payload);
|
|
127
|
+
}
|
|
128
|
+
async orderPlaced(payload) {
|
|
129
|
+
return this.dispatcher.emit("order-placed", payload);
|
|
130
|
+
}
|
|
131
|
+
async quoteRequested(payload) {
|
|
132
|
+
return this.dispatcher.emit("quote-requested", payload);
|
|
133
|
+
}
|
|
134
|
+
async orderReordered(payload) {
|
|
135
|
+
return this.dispatcher.emit("order-reordered", payload);
|
|
136
|
+
}
|
|
137
|
+
async companyRegistered(payload) {
|
|
138
|
+
return this.dispatcher.emit("company-registered", payload);
|
|
139
|
+
}
|
|
140
|
+
async userLoggedIn(payload) {
|
|
141
|
+
return this.dispatcher.emit("user-logged-in", payload);
|
|
142
|
+
}
|
|
143
|
+
async userLoggedOut(payload) {
|
|
144
|
+
return this.dispatcher.emit("user-logged-out", payload);
|
|
145
|
+
}
|
|
146
|
+
async userRegistered(payload) {
|
|
147
|
+
return this.dispatcher.emit("user-registered", payload);
|
|
148
|
+
}
|
|
149
|
+
async profileUpdated(payload) {
|
|
150
|
+
return this.dispatcher.emit("profile-updated", payload);
|
|
151
|
+
}
|
|
152
|
+
async consentChanged(payload) {
|
|
153
|
+
return this.dispatcher.emit("consent-changed", payload);
|
|
154
|
+
}
|
|
155
|
+
async newsletterSubscribed(payload) {
|
|
156
|
+
return this.dispatcher.emit("newsletter-subscribed", payload);
|
|
157
|
+
}
|
|
158
|
+
async wishlistItemAdded(payload) {
|
|
159
|
+
return this.dispatcher.emit("wishlist-item-added", payload);
|
|
160
|
+
}
|
|
161
|
+
async wishlistItemRemoved(payload) {
|
|
162
|
+
return this.dispatcher.emit("wishlist-item-removed", payload);
|
|
163
|
+
}
|
|
164
|
+
async backInStockRequested(payload) {
|
|
165
|
+
return this.dispatcher.emit("back-in-stock-requested", payload);
|
|
166
|
+
}
|
|
167
|
+
async reviewSubmitted(payload) {
|
|
168
|
+
return this.dispatcher.emit("review-submitted", payload);
|
|
169
|
+
}
|
|
170
|
+
async storeSelected(payload) {
|
|
171
|
+
return this.dispatcher.emit("store-selected", payload);
|
|
172
|
+
}
|
|
173
|
+
async productShared(payload) {
|
|
174
|
+
return this.dispatcher.emit("product-shared", payload);
|
|
175
|
+
}
|
|
176
|
+
async custom(payload) {
|
|
177
|
+
return this.dispatcher.emit("custom", payload);
|
|
98
178
|
}
|
|
99
179
|
}
|
|
100
180
|
__decorateClass([
|
|
101
|
-
Reactionary({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
})
|
|
105
|
-
],
|
|
181
|
+
Reactionary({ inputSchema: AnalyticsMutationSchema, outputSchema: AnalyticsResultSchema })
|
|
182
|
+
], AnalyticsCapability.prototype, "track", 1);
|
|
183
|
+
__decorateClass([
|
|
184
|
+
Reactionary({ inputSchema: AnalyticsMutationPageViewedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
185
|
+
], AnalyticsCapability.prototype, "pageViewed", 1);
|
|
186
|
+
__decorateClass([
|
|
187
|
+
Reactionary({ inputSchema: AnalyticsMutationSearchResultsViewedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
188
|
+
], AnalyticsCapability.prototype, "searchResultsViewed", 1);
|
|
189
|
+
__decorateClass([
|
|
190
|
+
Reactionary({ inputSchema: AnalyticsMutationAutocompleteSuggestionSelectedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
191
|
+
], AnalyticsCapability.prototype, "autocompleteSuggestionSelected", 1);
|
|
192
|
+
__decorateClass([
|
|
193
|
+
Reactionary({ inputSchema: AnalyticsMutationCategoryViewedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
194
|
+
], AnalyticsCapability.prototype, "categoryViewed", 1);
|
|
195
|
+
__decorateClass([
|
|
196
|
+
Reactionary({ inputSchema: AnalyticsMutationProductCarouselViewedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
197
|
+
], AnalyticsCapability.prototype, "productCarouselViewed", 1);
|
|
198
|
+
__decorateClass([
|
|
199
|
+
Reactionary({ inputSchema: AnalyticsMutationProductClickedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
200
|
+
], AnalyticsCapability.prototype, "productClicked", 1);
|
|
201
|
+
__decorateClass([
|
|
202
|
+
Reactionary({ inputSchema: AnalyticsMutationProductViewedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
203
|
+
], AnalyticsCapability.prototype, "productViewed", 1);
|
|
204
|
+
__decorateClass([
|
|
205
|
+
Reactionary({ inputSchema: AnalyticsMutationPromotionViewedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
206
|
+
], AnalyticsCapability.prototype, "promotionViewed", 1);
|
|
207
|
+
__decorateClass([
|
|
208
|
+
Reactionary({ inputSchema: AnalyticsMutationPromotionClickedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
209
|
+
], AnalyticsCapability.prototype, "promotionClicked", 1);
|
|
210
|
+
__decorateClass([
|
|
211
|
+
Reactionary({ inputSchema: AnalyticsMutationCartItemAddedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
212
|
+
], AnalyticsCapability.prototype, "cartItemAdded", 1);
|
|
213
|
+
__decorateClass([
|
|
214
|
+
Reactionary({ inputSchema: AnalyticsMutationCartItemRemovedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
215
|
+
], AnalyticsCapability.prototype, "cartItemRemoved", 1);
|
|
216
|
+
__decorateClass([
|
|
217
|
+
Reactionary({ inputSchema: AnalyticsMutationCartItemQuantityChangedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
218
|
+
], AnalyticsCapability.prototype, "cartItemQuantityChanged", 1);
|
|
219
|
+
__decorateClass([
|
|
220
|
+
Reactionary({ inputSchema: AnalyticsMutationCartViewedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
221
|
+
], AnalyticsCapability.prototype, "cartViewed", 1);
|
|
222
|
+
__decorateClass([
|
|
223
|
+
Reactionary({ inputSchema: AnalyticsMutationCouponAppliedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
224
|
+
], AnalyticsCapability.prototype, "couponApplied", 1);
|
|
225
|
+
__decorateClass([
|
|
226
|
+
Reactionary({ inputSchema: AnalyticsMutationCouponRejectedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
227
|
+
], AnalyticsCapability.prototype, "couponRejected", 1);
|
|
228
|
+
__decorateClass([
|
|
229
|
+
Reactionary({ inputSchema: AnalyticsMutationCheckoutStartedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
230
|
+
], AnalyticsCapability.prototype, "checkoutStarted", 1);
|
|
231
|
+
__decorateClass([
|
|
232
|
+
Reactionary({ inputSchema: AnalyticsMutationShippingInfoAddedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
233
|
+
], AnalyticsCapability.prototype, "shippingInfoAdded", 1);
|
|
234
|
+
__decorateClass([
|
|
235
|
+
Reactionary({ inputSchema: AnalyticsMutationPaymentInfoAddedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
236
|
+
], AnalyticsCapability.prototype, "paymentInfoAdded", 1);
|
|
237
|
+
__decorateClass([
|
|
238
|
+
Reactionary({ inputSchema: AnalyticsMutationOrderPlacedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
239
|
+
], AnalyticsCapability.prototype, "orderPlaced", 1);
|
|
240
|
+
__decorateClass([
|
|
241
|
+
Reactionary({ inputSchema: AnalyticsMutationQuoteRequestedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
242
|
+
], AnalyticsCapability.prototype, "quoteRequested", 1);
|
|
243
|
+
__decorateClass([
|
|
244
|
+
Reactionary({ inputSchema: AnalyticsMutationOrderReorderedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
245
|
+
], AnalyticsCapability.prototype, "orderReordered", 1);
|
|
246
|
+
__decorateClass([
|
|
247
|
+
Reactionary({ inputSchema: AnalyticsMutationCompanyRegisteredSchema, outputSchema: AnalyticsEventResultSchema })
|
|
248
|
+
], AnalyticsCapability.prototype, "companyRegistered", 1);
|
|
249
|
+
__decorateClass([
|
|
250
|
+
Reactionary({ inputSchema: AnalyticsMutationUserLoggedInSchema, outputSchema: AnalyticsEventResultSchema })
|
|
251
|
+
], AnalyticsCapability.prototype, "userLoggedIn", 1);
|
|
252
|
+
__decorateClass([
|
|
253
|
+
Reactionary({ inputSchema: AnalyticsMutationUserLoggedOutSchema, outputSchema: AnalyticsEventResultSchema })
|
|
254
|
+
], AnalyticsCapability.prototype, "userLoggedOut", 1);
|
|
255
|
+
__decorateClass([
|
|
256
|
+
Reactionary({ inputSchema: AnalyticsMutationUserRegisteredSchema, outputSchema: AnalyticsEventResultSchema })
|
|
257
|
+
], AnalyticsCapability.prototype, "userRegistered", 1);
|
|
258
|
+
__decorateClass([
|
|
259
|
+
Reactionary({ inputSchema: AnalyticsMutationProfileUpdatedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
260
|
+
], AnalyticsCapability.prototype, "profileUpdated", 1);
|
|
261
|
+
__decorateClass([
|
|
262
|
+
Reactionary({ inputSchema: AnalyticsMutationConsentChangedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
263
|
+
], AnalyticsCapability.prototype, "consentChanged", 1);
|
|
264
|
+
__decorateClass([
|
|
265
|
+
Reactionary({ inputSchema: AnalyticsMutationNewsletterSubscribedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
266
|
+
], AnalyticsCapability.prototype, "newsletterSubscribed", 1);
|
|
267
|
+
__decorateClass([
|
|
268
|
+
Reactionary({ inputSchema: AnalyticsMutationWishlistItemAddedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
269
|
+
], AnalyticsCapability.prototype, "wishlistItemAdded", 1);
|
|
270
|
+
__decorateClass([
|
|
271
|
+
Reactionary({ inputSchema: AnalyticsMutationWishlistItemRemovedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
272
|
+
], AnalyticsCapability.prototype, "wishlistItemRemoved", 1);
|
|
273
|
+
__decorateClass([
|
|
274
|
+
Reactionary({ inputSchema: AnalyticsMutationBackInStockRequestedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
275
|
+
], AnalyticsCapability.prototype, "backInStockRequested", 1);
|
|
276
|
+
__decorateClass([
|
|
277
|
+
Reactionary({ inputSchema: AnalyticsMutationReviewSubmittedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
278
|
+
], AnalyticsCapability.prototype, "reviewSubmitted", 1);
|
|
279
|
+
__decorateClass([
|
|
280
|
+
Reactionary({ inputSchema: AnalyticsMutationStoreSelectedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
281
|
+
], AnalyticsCapability.prototype, "storeSelected", 1);
|
|
282
|
+
__decorateClass([
|
|
283
|
+
Reactionary({ inputSchema: AnalyticsMutationProductSharedSchema, outputSchema: AnalyticsEventResultSchema })
|
|
284
|
+
], AnalyticsCapability.prototype, "productShared", 1);
|
|
285
|
+
__decorateClass([
|
|
286
|
+
Reactionary({ inputSchema: AnalyticsMutationCustomSchema, outputSchema: AnalyticsEventResultSchema })
|
|
287
|
+
], AnalyticsCapability.prototype, "custom", 1);
|
|
106
288
|
export {
|
|
107
|
-
AnalyticsCapability
|
|
108
|
-
MulticastAnalyticsCapability
|
|
289
|
+
AnalyticsCapability
|
|
109
290
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCapability } from "./base.capability.js";
|
|
2
|
+
class AnalyticsProvider extends BaseCapability {
|
|
3
|
+
/** Unique within a client. Used in logs and tracing. Defaults to the resource name. */
|
|
4
|
+
get name() {
|
|
5
|
+
return this.getResourceName();
|
|
6
|
+
}
|
|
7
|
+
getResourceName() {
|
|
8
|
+
return "analytics";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
AnalyticsProvider
|
|
13
|
+
};
|
package/capabilities/index.js
CHANGED
package/client/client-builder.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { NoOpCache } from "../cache/noop-cache.js";
|
|
2
|
-
import {
|
|
2
|
+
import { AnalyticsCapability } from "../capabilities/analytics.capability.js";
|
|
3
|
+
import { createAnalyticsContext } from "../analytics/context.js";
|
|
4
|
+
import { AnalyticsDispatcher } from "../analytics/dispatcher.js";
|
|
3
5
|
import {
|
|
4
6
|
RequestContextSchema
|
|
5
7
|
} from "../schemas/session.schema.js";
|
|
@@ -9,33 +11,44 @@ class ClientBuilder {
|
|
|
9
11
|
cache;
|
|
10
12
|
context;
|
|
11
13
|
collisionStrategy = "last-wins";
|
|
14
|
+
analyticsOptions = {};
|
|
15
|
+
analyticsSubscribers = [];
|
|
12
16
|
constructor(context) {
|
|
13
17
|
this.context = context;
|
|
14
18
|
}
|
|
15
19
|
withCapability(factory) {
|
|
16
|
-
const newBuilder =
|
|
20
|
+
const newBuilder = this.clone();
|
|
17
21
|
newBuilder.factories = [...this.factories, factory];
|
|
18
|
-
newBuilder.cache = this.cache;
|
|
19
|
-
newBuilder.context = this.context;
|
|
20
|
-
newBuilder.collisionStrategy = this.collisionStrategy;
|
|
21
22
|
return newBuilder;
|
|
22
23
|
}
|
|
23
24
|
withCache(cache) {
|
|
24
|
-
const newBuilder =
|
|
25
|
-
newBuilder.factories = [...this.factories];
|
|
25
|
+
const newBuilder = this.clone();
|
|
26
26
|
newBuilder.cache = cache;
|
|
27
|
-
newBuilder.context = this.context;
|
|
28
|
-
newBuilder.collisionStrategy = this.collisionStrategy;
|
|
29
27
|
return newBuilder;
|
|
30
28
|
}
|
|
31
29
|
withCollisionStrategy(strategy) {
|
|
32
|
-
const newBuilder =
|
|
33
|
-
newBuilder.factories = [...this.factories];
|
|
34
|
-
newBuilder.cache = this.cache;
|
|
35
|
-
newBuilder.context = this.context;
|
|
30
|
+
const newBuilder = this.clone();
|
|
36
31
|
newBuilder.collisionStrategy = strategy;
|
|
37
32
|
return newBuilder;
|
|
38
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Configures how analytics events are delivered, e.g. `{ waitUntil: after }` in Next.js so vendor calls finish after the
|
|
36
|
+
* response, or a `defaultConsent` for requests whose session carries no consent. Optional.
|
|
37
|
+
*/
|
|
38
|
+
withAnalyticsDispatch(options) {
|
|
39
|
+
const newBuilder = this.clone();
|
|
40
|
+
newBuilder.analyticsOptions = { ...this.analyticsOptions, ...options };
|
|
41
|
+
return newBuilder;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Adds a custom analytics subscriber next to the providers registered by capability factories. Subscriptions are
|
|
45
|
+
* fixed at build time; there is no way to subscribe at runtime.
|
|
46
|
+
*/
|
|
47
|
+
withAnalyticsSubscriber(subscriber) {
|
|
48
|
+
const newBuilder = this.clone();
|
|
49
|
+
newBuilder.analyticsSubscribers = [...this.analyticsSubscribers, subscriber];
|
|
50
|
+
return newBuilder;
|
|
51
|
+
}
|
|
39
52
|
build() {
|
|
40
53
|
let client = {};
|
|
41
54
|
const sharedCache = this.cache || new NoOpCache();
|
|
@@ -43,26 +56,42 @@ class ClientBuilder {
|
|
|
43
56
|
if (!validatedContext.success) {
|
|
44
57
|
throw new Error("Invalid context: " + validatedContext.error);
|
|
45
58
|
}
|
|
46
|
-
const
|
|
59
|
+
const analyticsProviders = [];
|
|
47
60
|
const mergedProductRecommendations = [];
|
|
48
61
|
for (const factory of this.factories) {
|
|
49
62
|
const capability = this.resolveFactory(factory, sharedCache, this.context);
|
|
50
63
|
client = this.mergeCapabilities(client, capability);
|
|
51
64
|
if (capability.analytics) {
|
|
52
|
-
|
|
65
|
+
analyticsProviders.push(capability.analytics);
|
|
53
66
|
}
|
|
54
67
|
if (capability.productRecommendations) {
|
|
55
68
|
mergedProductRecommendations.push(capability.productRecommendations);
|
|
56
69
|
}
|
|
57
70
|
}
|
|
71
|
+
const dispatcher = new AnalyticsDispatcher({
|
|
72
|
+
requestContext: this.context,
|
|
73
|
+
subscribers: [...analyticsProviders, ...this.analyticsSubscribers],
|
|
74
|
+
// Lookups use the client's own capabilities (and so its cache); `client` is complete by the time anything is flushed.
|
|
75
|
+
createContext: () => createAnalyticsContext({ capabilities: client, requestContext: this.context }),
|
|
76
|
+
options: this.analyticsOptions
|
|
77
|
+
});
|
|
58
78
|
const completeClient = {
|
|
59
79
|
...client,
|
|
60
|
-
analytics: new
|
|
80
|
+
analytics: new AnalyticsCapability(sharedCache, this.context, dispatcher),
|
|
61
81
|
productRecommendations: new MulticastProductRecommendationsCapability(sharedCache, this.context, mergedProductRecommendations),
|
|
62
82
|
cache: sharedCache
|
|
63
83
|
};
|
|
64
84
|
return completeClient;
|
|
65
85
|
}
|
|
86
|
+
clone() {
|
|
87
|
+
const newBuilder = new ClientBuilder(this.context);
|
|
88
|
+
newBuilder.factories = [...this.factories];
|
|
89
|
+
newBuilder.cache = this.cache;
|
|
90
|
+
newBuilder.collisionStrategy = this.collisionStrategy;
|
|
91
|
+
newBuilder.analyticsOptions = this.analyticsOptions;
|
|
92
|
+
newBuilder.analyticsSubscribers = [...this.analyticsSubscribers];
|
|
93
|
+
return newBuilder;
|
|
94
|
+
}
|
|
66
95
|
resolveFactory(factory, cache, context) {
|
|
67
96
|
if (factory.length <= 1) {
|
|
68
97
|
return factory({ cache, context });
|
package/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./client/index.js";
|
|
|
3
3
|
export * from "./decorators/index.js";
|
|
4
4
|
export * from "./factories/index.js";
|
|
5
5
|
export * from "./capabilities/index.js";
|
|
6
|
+
export * from "./analytics/index.js";
|
|
6
7
|
export * from "./schemas/index.js";
|
|
7
8
|
export * from "./initialization.js";
|
|
8
9
|
export * from "./metrics/protocol.js";
|
package/package.json
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
const AnalyticsPurposeSchema = z.enum(["necessary", "analytics", "marketing"]).meta({ description: 'The purpose an analytics subscriber processes events for. "necessary" is always allowed; the others require granted consent.' });
|
|
3
|
+
const AnalyticsConsentSchema = z.looseObject({
|
|
4
|
+
analytics: z.boolean().meta({ description: "True if the visitor has granted consent to analytics processing." }),
|
|
5
|
+
marketing: z.boolean().meta({ description: "True if the visitor has granted consent to marketing processing." })
|
|
6
|
+
});
|
|
7
|
+
export {
|
|
8
|
+
AnalyticsConsentSchema,
|
|
9
|
+
AnalyticsPurposeSchema
|
|
10
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { AnalyticsConsentSchema, AnalyticsPurposeSchema } from "./consent.model.js";
|
|
3
|
+
const AnalyticsSubscriberDescriptorSchema = z.looseObject({
|
|
4
|
+
name: z.string().min(1).meta({ description: 'Unique subscriber name, e.g. "unomi" or "algolia". Used in logs and tracing.' }),
|
|
5
|
+
types: z.array(z.string().min(1)).min(1).meta({ description: 'Event types handled: an exact type, a prefix wildcard such as "cart-*", or "*".' }),
|
|
6
|
+
purpose: AnalyticsPurposeSchema
|
|
7
|
+
});
|
|
8
|
+
const AnalyticsDispatchOptionsSchema = z.looseObject({
|
|
9
|
+
waitUntil: z.custom((value) => typeof value === "function", "waitUntil must be a function").optional().meta({ description: "Called with the delivery promise so the runtime keeps it alive after the response. Without it, delivery is fire-and-forget with errors logged." }),
|
|
10
|
+
defaultConsent: AnalyticsConsentSchema.optional().meta({ description: "Consent applied when the session carries none. Defaults to everything granted, which preserves behaviour from before consent existed." })
|
|
11
|
+
});
|
|
12
|
+
export {
|
|
13
|
+
AnalyticsDispatchOptionsSchema,
|
|
14
|
+
AnalyticsSubscriberDescriptorSchema
|
|
15
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { PersonalizationProfileIdentifierSchema } from "../identifiers.model.js";
|
|
3
|
+
import { IdentitySchema } from "../identity.model.js";
|
|
4
|
+
import { CurrencySchema } from "../currency.model.js";
|
|
5
|
+
import { AnalyticsConsentSchema } from "./consent.model.js";
|
|
6
|
+
import { OriginSchema } from "./origin.model.js";
|
|
7
|
+
const AnalyticsPageSchema = z.looseObject({
|
|
8
|
+
url: z.string().optional(),
|
|
9
|
+
title: z.string().optional(),
|
|
10
|
+
referrer: z.string().optional()
|
|
11
|
+
});
|
|
12
|
+
const EventContextSnapshotSchema = z.looseObject({
|
|
13
|
+
marketingIdentifier: PersonalizationProfileIdentifierSchema.meta({ description: "The marketing (CDP) identifier of the visitor at emit time." }),
|
|
14
|
+
identity: IdentitySchema.meta({ description: "The identity of the visitor at emit time. Anonymous when not logged in." }),
|
|
15
|
+
locale: z.string(),
|
|
16
|
+
currency: CurrencySchema,
|
|
17
|
+
consent: AnalyticsConsentSchema.optional().meta({ description: "Consent at emit time. Absent when the request carried none and no default applied." }),
|
|
18
|
+
page: AnalyticsPageSchema.optional(),
|
|
19
|
+
userAgent: z.string().optional().meta({ description: "The user agent of the visitor's request, if known. Delivery happens after the request, so subscribers cannot read it from the request context later." }),
|
|
20
|
+
clientIp: z.string().optional().meta({ description: "The IP address of the visitor's request, if known. Personal data: capturing it does not forward it, each subscriber decides what to send to its vendor." }),
|
|
21
|
+
isBot: z.boolean().optional().meta({ description: "True if the request was identified as a bot or crawler." })
|
|
22
|
+
});
|
|
23
|
+
const AnalyticsEventEnvelopeSchema = z.looseObject({
|
|
24
|
+
id: z.string().meta({ description: "Unique event id (UUID). Used for deduplication by vendors and for debugging." }),
|
|
25
|
+
occurredAt: z.iso.datetime().meta({ description: "ISO timestamp taken when the storefront emitted the event." }),
|
|
26
|
+
origin: OriginSchema.optional(),
|
|
27
|
+
properties: z.record(z.string(), z.unknown()).optional().meta({ description: "Storefront-only knowledge. Not a channel for product data; providers look that up." }),
|
|
28
|
+
context: EventContextSnapshotSchema
|
|
29
|
+
});
|
|
30
|
+
const AnalyticsEventResultSchema = z.looseObject({
|
|
31
|
+
eventId: z.string().meta({ description: "The id assigned to the enqueued event." })
|
|
32
|
+
});
|
|
33
|
+
export {
|
|
34
|
+
AnalyticsEventEnvelopeSchema,
|
|
35
|
+
AnalyticsEventResultSchema,
|
|
36
|
+
AnalyticsPageSchema,
|
|
37
|
+
EventContextSnapshotSchema
|
|
38
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { CategorySchema } from "../category.model.js";
|
|
3
|
+
import {
|
|
4
|
+
CategoryIdentifierSchema,
|
|
5
|
+
ProductIdentifierSchema,
|
|
6
|
+
ProductRecommendationIdentifierSchema,
|
|
7
|
+
StoreIdentifierSchema
|
|
8
|
+
} from "../identifiers.model.js";
|
|
9
|
+
import { ProductSchema } from "../product.model.js";
|
|
10
|
+
import { StoreSchema } from "../store.model.js";
|
|
11
|
+
const PageTypeSchema = z.enum(["home", "category", "search", "pdp", "cart", "checkout", "content", "account", "other"]).meta({ description: "The kind of page that was viewed." });
|
|
12
|
+
const AnalyticsPageViewSchema = z.looseObject({
|
|
13
|
+
type: PageTypeSchema,
|
|
14
|
+
url: z.string().optional(),
|
|
15
|
+
title: z.string().optional()
|
|
16
|
+
});
|
|
17
|
+
const AnalyticsPromotionSchema = z.looseObject({
|
|
18
|
+
id: z.string().meta({ description: "The promotion id." }),
|
|
19
|
+
name: z.string(),
|
|
20
|
+
slot: z.string().meta({ description: 'The placement of the promotion, e.g. "hero".' }),
|
|
21
|
+
creative: z.string().optional().meta({ description: "The creative shown, if the storefront distinguishes creatives." })
|
|
22
|
+
});
|
|
23
|
+
const AnalyticsCarouselSchema = z.looseObject({
|
|
24
|
+
recommendationId: ProductRecommendationIdentifierSchema.optional().meta({ description: "The recommendation the carousel was built from, if any." }),
|
|
25
|
+
carouselName: z.string().meta({ description: "Storefront name of the carousel." })
|
|
26
|
+
});
|
|
27
|
+
const AnalyticsAutocompleteSuggestionSchema = z.discriminatedUnion("type", [
|
|
28
|
+
z.looseObject({ type: z.literal("term"), term: z.string() }),
|
|
29
|
+
z.looseObject({ type: z.literal("product"), product: ProductIdentifierSchema })
|
|
30
|
+
]);
|
|
31
|
+
const AnalyticsProductRefSchema = z.union([ProductIdentifierSchema, ProductSchema]);
|
|
32
|
+
const AnalyticsCategoryRefSchema = z.union([CategoryIdentifierSchema, CategorySchema]);
|
|
33
|
+
const AnalyticsStoreRefSchema = z.union([StoreIdentifierSchema, StoreSchema]);
|
|
34
|
+
const AnalyticsCouponRejectionReasonSchema = z.string().meta({ description: "Why the coupon was rejected, as reported by the backend or storefront." });
|
|
35
|
+
const AnalyticsChannelSchema = z.string().meta({ description: 'A channel, e.g. "email" for newsletters or "facebook" for sharing.' });
|
|
36
|
+
export {
|
|
37
|
+
AnalyticsAutocompleteSuggestionSchema,
|
|
38
|
+
AnalyticsCarouselSchema,
|
|
39
|
+
AnalyticsCategoryRefSchema,
|
|
40
|
+
AnalyticsChannelSchema,
|
|
41
|
+
AnalyticsCouponRejectionReasonSchema,
|
|
42
|
+
AnalyticsPageViewSchema,
|
|
43
|
+
AnalyticsProductRefSchema,
|
|
44
|
+
AnalyticsPromotionSchema,
|
|
45
|
+
AnalyticsStoreRefSchema,
|
|
46
|
+
PageTypeSchema
|
|
47
|
+
};
|