@searchspring/snap-controller 0.73.7 → 0.75.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/dist/cjs/Autocomplete/AutocompleteController.d.ts +0 -1
- package/dist/cjs/Autocomplete/AutocompleteController.d.ts.map +1 -1
- package/dist/cjs/Autocomplete/AutocompleteController.js +124 -68
- package/dist/cjs/Finder/FinderController.d.ts.map +1 -1
- package/dist/cjs/Finder/FinderController.js +3 -0
- package/dist/cjs/Recommendation/RecommendationController.d.ts.map +1 -1
- package/dist/cjs/Recommendation/RecommendationController.js +84 -58
- package/dist/cjs/Search/SearchController.d.ts.map +1 -1
- package/dist/cjs/Search/SearchController.js +142 -66
- package/dist/cjs/utils/isClickWithinProductLink.d.ts +1 -1
- package/dist/cjs/utils/isClickWithinProductLink.d.ts.map +1 -1
- package/dist/cjs/utils/isClickWithinProductLink.js +14 -12
- package/dist/esm/Autocomplete/AutocompleteController.d.ts +0 -1
- package/dist/esm/Autocomplete/AutocompleteController.d.ts.map +1 -1
- package/dist/esm/Autocomplete/AutocompleteController.js +101 -28
- package/dist/esm/Finder/FinderController.d.ts.map +1 -1
- package/dist/esm/Finder/FinderController.js +3 -0
- package/dist/esm/Recommendation/RecommendationController.d.ts.map +1 -1
- package/dist/esm/Recommendation/RecommendationController.js +64 -22
- package/dist/esm/Search/SearchController.d.ts.map +1 -1
- package/dist/esm/Search/SearchController.js +106 -22
- package/dist/esm/utils/isClickWithinProductLink.d.ts +1 -1
- package/dist/esm/utils/isClickWithinProductLink.d.ts.map +1 -1
- package/dist/esm/utils/isClickWithinProductLink.js +13 -12
- package/package.json +10 -10
|
@@ -16,6 +16,9 @@ const defaultConfig = {
|
|
|
16
16
|
selector: '',
|
|
17
17
|
action: '',
|
|
18
18
|
globals: {},
|
|
19
|
+
beacon: {
|
|
20
|
+
enabled: true,
|
|
21
|
+
},
|
|
19
22
|
settings: {
|
|
20
23
|
integratedSpellCorrection: false,
|
|
21
24
|
initializeFromUrl: true,
|
|
@@ -43,8 +46,16 @@ export class AutocompleteController extends AbstractController {
|
|
|
43
46
|
this.track = {
|
|
44
47
|
banner: {
|
|
45
48
|
impression: (_banner) => {
|
|
49
|
+
if (!_banner) {
|
|
50
|
+
this.log.warn('No banner provided to track.banner.impression');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
46
53
|
const { responseId, uid } = _banner;
|
|
47
|
-
if (this.events[responseId]
|
|
54
|
+
if (!this.events[responseId]) {
|
|
55
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
else if (this.events?.[responseId]?.banner?.[uid]?.impression) {
|
|
48
59
|
return;
|
|
49
60
|
}
|
|
50
61
|
const banner = { uid };
|
|
@@ -54,12 +65,20 @@ export class AutocompleteController extends AbstractController {
|
|
|
54
65
|
results: [],
|
|
55
66
|
};
|
|
56
67
|
this.eventManager.fire('track.banner.impression', { controller: this, product: { uid }, trackEvent: data });
|
|
57
|
-
this.tracker.events.autocomplete.impression({ data, siteId: this.config.globals?.siteId });
|
|
68
|
+
this.config.beacon?.enabled && this.tracker.events.autocomplete.impression({ data, siteId: this.config.globals?.siteId });
|
|
58
69
|
this.events[responseId].banner[uid] = this.events[responseId].banner[uid] || {};
|
|
59
70
|
this.events[responseId].banner[uid].impression = true;
|
|
60
71
|
},
|
|
61
72
|
click: (e, banner) => {
|
|
73
|
+
if (!banner) {
|
|
74
|
+
this.log.warn('No banner provided to track.banner.click');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
62
77
|
const { responseId, uid } = banner;
|
|
78
|
+
if (!this.events[responseId]) {
|
|
79
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
63
82
|
if (isClickWithinBannerLink(e)) {
|
|
64
83
|
if (this.events?.[responseId]?.banner[uid]?.clickThrough) {
|
|
65
84
|
return;
|
|
@@ -73,13 +92,21 @@ export class AutocompleteController extends AbstractController {
|
|
|
73
92
|
}
|
|
74
93
|
},
|
|
75
94
|
clickThrough: (e, { uid, responseId }) => {
|
|
95
|
+
if (!uid) {
|
|
96
|
+
this.log.warn('No banner uid provided to track.banner.clickThrough');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (!this.events[responseId]) {
|
|
100
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
76
103
|
const banner = { uid };
|
|
77
104
|
const data = {
|
|
78
105
|
responseId,
|
|
79
106
|
banners: [banner],
|
|
80
107
|
};
|
|
81
108
|
this.eventManager.fire('track.banner.clickThrough', { controller: this, event: e, product: { uid }, trackEvent: data });
|
|
82
|
-
this.tracker.events.autocomplete.clickThrough({ data, siteId: this.config.globals?.siteId });
|
|
109
|
+
this.config.beacon?.enabled && this.tracker.events.autocomplete.clickThrough({ data, siteId: this.config.globals?.siteId });
|
|
83
110
|
this.events[responseId].banner[uid] = this.events[responseId].banner[uid] || {};
|
|
84
111
|
this.events[responseId].banner[uid].clickThrough = true;
|
|
85
112
|
setTimeout(() => {
|
|
@@ -89,22 +116,43 @@ export class AutocompleteController extends AbstractController {
|
|
|
89
116
|
},
|
|
90
117
|
product: {
|
|
91
118
|
clickThrough: (e, result) => {
|
|
119
|
+
if (!result) {
|
|
120
|
+
this.log.warn('No result provided to track.product.clickThrough');
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
92
123
|
const responseId = result.responseId;
|
|
124
|
+
if (!this.events[responseId]) {
|
|
125
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const type = (['product', 'banner'].includes(result.type) ? result.type : 'product');
|
|
93
129
|
const item = {
|
|
94
|
-
type
|
|
95
|
-
uid: result.id,
|
|
96
|
-
|
|
97
|
-
|
|
130
|
+
type,
|
|
131
|
+
uid: result.id ? '' + result.id : '',
|
|
132
|
+
...(type === 'product'
|
|
133
|
+
? {
|
|
134
|
+
parentId: result.id ? '' + result.id : '',
|
|
135
|
+
sku: result.mappings.core?.sku ? '' + result.mappings.core?.sku : undefined,
|
|
136
|
+
}
|
|
137
|
+
: {}),
|
|
98
138
|
};
|
|
99
139
|
const data = {
|
|
100
140
|
responseId,
|
|
101
141
|
results: [item],
|
|
102
142
|
};
|
|
103
143
|
this.eventManager.fire('track.product.clickThrough', { controller: this, event: e, product: result, trackEvent: data });
|
|
104
|
-
this.tracker.events.autocomplete.clickThrough({ data, siteId: this.config.globals?.siteId });
|
|
144
|
+
this.config.beacon?.enabled && this.tracker.events.autocomplete.clickThrough({ data, siteId: this.config.globals?.siteId });
|
|
105
145
|
},
|
|
106
146
|
click: (e, result) => {
|
|
147
|
+
if (!result) {
|
|
148
|
+
this.log.warn('No result provided to track.product.click');
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
107
151
|
const responseId = result.responseId;
|
|
152
|
+
if (!this.events[responseId]) {
|
|
153
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
108
156
|
if (result.type === 'banner' && isClickWithinBannerLink(e)) {
|
|
109
157
|
if (this.events?.[responseId]?.product[result.id]?.inlineBannerClickThrough) {
|
|
110
158
|
return;
|
|
@@ -129,15 +177,28 @@ export class AutocompleteController extends AbstractController {
|
|
|
129
177
|
}
|
|
130
178
|
},
|
|
131
179
|
impression: (result) => {
|
|
180
|
+
if (!result) {
|
|
181
|
+
this.log.warn('No result provided to track.product.impression');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
132
184
|
const responseId = result.responseId;
|
|
133
|
-
if (this.events
|
|
185
|
+
if (!this.events[responseId]) {
|
|
186
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
else if (this.events?.[responseId]?.product[result.id]?.impression) {
|
|
134
190
|
return;
|
|
135
191
|
}
|
|
192
|
+
const type = (['product', 'banner'].includes(result.type) ? result.type : 'product');
|
|
136
193
|
const item = {
|
|
137
|
-
type
|
|
138
|
-
uid: result.id,
|
|
139
|
-
|
|
140
|
-
|
|
194
|
+
type,
|
|
195
|
+
uid: result.id ? '' + result.id : '',
|
|
196
|
+
...(type === 'product'
|
|
197
|
+
? {
|
|
198
|
+
parentId: result.id ? '' + result.id : '',
|
|
199
|
+
sku: result.mappings.core?.sku ? '' + result.mappings.core?.sku : undefined,
|
|
200
|
+
}
|
|
201
|
+
: {}),
|
|
141
202
|
};
|
|
142
203
|
const data = {
|
|
143
204
|
responseId,
|
|
@@ -145,12 +206,20 @@ export class AutocompleteController extends AbstractController {
|
|
|
145
206
|
banners: [],
|
|
146
207
|
};
|
|
147
208
|
this.eventManager.fire('track.product.impression', { controller: this, product: result, trackEvent: data });
|
|
148
|
-
this.tracker.events.autocomplete.impression({ data, siteId: this.config.globals?.siteId });
|
|
209
|
+
this.config.beacon?.enabled && this.tracker.events.autocomplete.impression({ data, siteId: this.config.globals?.siteId });
|
|
149
210
|
this.events[responseId].product[result.id] = this.events[responseId].product[result.id] || {};
|
|
150
211
|
this.events[responseId].product[result.id].impression = true;
|
|
151
212
|
},
|
|
152
213
|
addToCart: (result) => {
|
|
214
|
+
if (!result) {
|
|
215
|
+
this.log.warn('No result provided to track.product.addToCart');
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
153
218
|
const responseId = result.responseId;
|
|
219
|
+
if (!this.events[responseId]) {
|
|
220
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
154
223
|
const product = {
|
|
155
224
|
parentId: result.id,
|
|
156
225
|
uid: result.id,
|
|
@@ -163,16 +232,20 @@ export class AutocompleteController extends AbstractController {
|
|
|
163
232
|
results: [product],
|
|
164
233
|
};
|
|
165
234
|
this.eventManager.fire('track.product.addToCart', { controller: this, product: result, trackEvent: data });
|
|
166
|
-
this.tracker.events.autocomplete.addToCart({ data, siteId: this.config.globals?.siteId });
|
|
235
|
+
this.config.beacon?.enabled && this.tracker.events.autocomplete.addToCart({ data, siteId: this.config.globals?.siteId });
|
|
167
236
|
},
|
|
168
237
|
},
|
|
169
238
|
redirect: ({ redirectURL, responseId }) => {
|
|
239
|
+
if (!redirectURL) {
|
|
240
|
+
this.log.warn('No redirectURL provided to track.redirect');
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
170
243
|
const data = {
|
|
171
244
|
responseId,
|
|
172
245
|
redirect: redirectURL,
|
|
173
246
|
};
|
|
174
247
|
this.eventManager.fire('track.redirect', { controller: this, redirectURL, trackEvent: data });
|
|
175
|
-
this.tracker.events.autocomplete.redirect({ data, siteId: this.config.globals?.siteId });
|
|
248
|
+
this.config.beacon?.enabled && this.tracker.events.autocomplete.redirect({ data, siteId: this.config.globals?.siteId });
|
|
176
249
|
},
|
|
177
250
|
};
|
|
178
251
|
this.handlers = {
|
|
@@ -425,7 +498,9 @@ export class AutocompleteController extends AbstractController {
|
|
|
425
498
|
this.log.profile(searchProfile);
|
|
426
499
|
const responseId = response.tracking.responseId;
|
|
427
500
|
this.events[responseId] = this.events[responseId] || { product: {}, banner: {} };
|
|
428
|
-
|
|
501
|
+
const previousResponseId = this.store.results[0]?.responseId;
|
|
502
|
+
const repeatedSearch = previousResponseId && previousResponseId === responseId;
|
|
503
|
+
if (repeatedSearch) {
|
|
429
504
|
const impressedResultIds = Object.keys(this.events[responseId].product || {}).filter((resultId) => this.events[responseId].product?.[resultId]?.impression);
|
|
430
505
|
this.events[responseId] = {
|
|
431
506
|
product: impressedResultIds.reduce((acc, resultId) => {
|
|
@@ -437,7 +512,6 @@ export class AutocompleteController extends AbstractController {
|
|
|
437
512
|
}
|
|
438
513
|
else {
|
|
439
514
|
this.events[responseId] = { product: {}, banner: {} };
|
|
440
|
-
this.lastSearchQuery = response.search?.query;
|
|
441
515
|
}
|
|
442
516
|
const afterSearchProfile = this.profiler.create({ type: 'event', name: 'afterSearch', context: params }).start();
|
|
443
517
|
try {
|
|
@@ -462,6 +536,10 @@ export class AutocompleteController extends AbstractController {
|
|
|
462
536
|
this.log.profile(afterSearchProfile);
|
|
463
537
|
// update the store
|
|
464
538
|
this.store.update(response);
|
|
539
|
+
if (!repeatedSearch) {
|
|
540
|
+
const data = { responseId };
|
|
541
|
+
this.config.beacon?.enabled && this.tracker.events.autocomplete.render({ data, siteId: this.config.globals?.siteId });
|
|
542
|
+
}
|
|
465
543
|
const afterStoreProfile = this.profiler.create({ type: 'event', name: 'afterStore', context: params }).start();
|
|
466
544
|
try {
|
|
467
545
|
await this.eventManager.fire('afterStore', {
|
|
@@ -530,7 +608,11 @@ export class AutocompleteController extends AbstractController {
|
|
|
530
608
|
}
|
|
531
609
|
};
|
|
532
610
|
this.addToCart = async (_products) => {
|
|
533
|
-
const products = typeof _products
|
|
611
|
+
const products = typeof _products?.slice == 'function' ? _products.slice() : [_products];
|
|
612
|
+
if (!_products || products.length === 0) {
|
|
613
|
+
this.log.warn('No products provided to autocomplete controller.addToCart');
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
534
616
|
products.forEach((product) => {
|
|
535
617
|
this.track.product.addToCart(product);
|
|
536
618
|
});
|
|
@@ -553,15 +635,6 @@ export class AutocompleteController extends AbstractController {
|
|
|
553
635
|
type: 'session',
|
|
554
636
|
key: `ss-controller-${this.config.id}`,
|
|
555
637
|
});
|
|
556
|
-
this.eventManager.on('afterStore', async (search, next) => {
|
|
557
|
-
await next();
|
|
558
|
-
const controller = search.controller;
|
|
559
|
-
const responseId = search.response.tracking.responseId;
|
|
560
|
-
if (controller.store.loaded && !controller.store.error) {
|
|
561
|
-
const data = { responseId };
|
|
562
|
-
this.tracker.events.autocomplete.render({ data, siteId: this.config.globals?.siteId });
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
638
|
// add 'afterSearch' middleware
|
|
566
639
|
this.eventManager.on('afterSearch', async (ac, next) => {
|
|
567
640
|
await next();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FinderController.d.ts","sourceRoot":"","sources":["../../../src/Finder/FinderController.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE,OAAO,KAAK,EAAE,sBAAsB,EAAwB,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"FinderController.d.ts","sourceRoot":"","sources":["../../../src/Finder/FinderController.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE,OAAO,KAAK,EAAE,sBAAsB,EAAwB,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAoBnH,qBAAa,gBAAiB,SAAQ,kBAAkB;IAChD,IAAI,kBAA0B;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,sBAAsB,CAAC;gBAGtC,MAAM,EAAE,sBAAsB,EAC9B,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IA+B3B,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA6BhC;IAED,IAAI,QAAa,QAAQ,IAAI,CAAC,CAkB5B;IAEF,KAAK,QAAO,IAAI,CAId;IAEF,MAAM,QAAa,QAAQ,IAAI,CAAC,CAoI9B;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecommendationController.d.ts","sourceRoot":"","sources":["../../../src/Recommendation/RecommendationController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAW3C,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"RecommendationController.d.ts","sourceRoot":"","sources":["../../../src/Recommendation/RecommendationController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAW3C,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGrG,KAAK,0BAA0B,GAAG;IACjC,OAAO,EAAE;QACR,YAAY,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;QACzD,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;QAC/C,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;KACrC,CAAC;CACF,CAAC;AAaF,qBAAa,wBAAyB,SAAQ,kBAAkB;IACxD,IAAI,kBAAkC;IACrC,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,8BAA8B,CAAC;IAE/C,OAAO,CAAC,MAAM,CAUP;gBAGN,MAAM,EAAE,8BAA8B,EACtC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IAwC3B,KAAK,EAAE,0BAA0B,CA0I/B;IAEF,IAAI,MAAM,IAAI,qBAAqB,CA4BlC;IAED,MAAM,QAAa,QAAQ,IAAI,CAAC,CAgI9B;IAEF,SAAS,cAAqB,OAAO,EAAE,GAAG,OAAO,KAAG,QAAQ,IAAI,CAAC,CAY/D;CACF"}
|
|
@@ -5,6 +5,9 @@ import { ControllerTypes } from '../types';
|
|
|
5
5
|
import { CLICK_DUPLICATION_TIMEOUT, isClickWithinProductLink } from '../utils/isClickWithinProductLink';
|
|
6
6
|
const defaultConfig = {
|
|
7
7
|
id: 'recommend',
|
|
8
|
+
beacon: {
|
|
9
|
+
enabled: true,
|
|
10
|
+
},
|
|
8
11
|
tag: '',
|
|
9
12
|
batched: true,
|
|
10
13
|
realtime: false,
|
|
@@ -18,14 +21,27 @@ export class RecommendationController extends AbstractController {
|
|
|
18
21
|
this.track = {
|
|
19
22
|
product: {
|
|
20
23
|
clickThrough: (e, result) => {
|
|
24
|
+
if (!result) {
|
|
25
|
+
this.log.warn('No result provided to track.product.clickThrough');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
21
28
|
const responseId = result.responseId;
|
|
29
|
+
if (!this.events[responseId]) {
|
|
30
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
22
33
|
if (this.events[responseId]?.product[result.id]?.productClickThrough)
|
|
23
34
|
return;
|
|
35
|
+
const type = (['product', 'banner'].includes(result.type) ? result.type : 'product');
|
|
24
36
|
const beaconResult = {
|
|
25
|
-
type
|
|
26
|
-
uid: result.id,
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
type,
|
|
38
|
+
uid: result.id ? '' + result.id : '',
|
|
39
|
+
...(type === 'product'
|
|
40
|
+
? {
|
|
41
|
+
parentId: result.id ? '' + result.id : '',
|
|
42
|
+
sku: result.mappings.core?.sku ? '' + result.mappings.core?.sku : undefined,
|
|
43
|
+
}
|
|
44
|
+
: {}),
|
|
29
45
|
};
|
|
30
46
|
const data = {
|
|
31
47
|
tag: this.store.profile.tag,
|
|
@@ -33,12 +49,20 @@ export class RecommendationController extends AbstractController {
|
|
|
33
49
|
results: [beaconResult],
|
|
34
50
|
};
|
|
35
51
|
this.eventManager.fire('track.product.clickThrough', { controller: this, event: e, product: result, trackEvent: data });
|
|
36
|
-
this.tracker.events.recommendations.clickThrough({ data, siteId: this.config.globals?.siteId });
|
|
52
|
+
this.config.beacon?.enabled && this.tracker.events.recommendations.clickThrough({ data, siteId: this.config.globals?.siteId });
|
|
37
53
|
this.events[responseId].product[result.id] = this.events[responseId].product[result.id] || {};
|
|
38
54
|
this.events[responseId].product[result.id].productClickThrough = true;
|
|
39
55
|
},
|
|
40
56
|
click: (e, result) => {
|
|
57
|
+
if (!result) {
|
|
58
|
+
this.log.warn('No result provided to track.product.click');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
41
61
|
const responseId = result.responseId;
|
|
62
|
+
if (!this.events[responseId]) {
|
|
63
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
42
66
|
if (result.type === 'banner') {
|
|
43
67
|
if (this.events[responseId]?.product[result.id]?.inlineBannerClickThrough) {
|
|
44
68
|
return;
|
|
@@ -63,15 +87,28 @@ export class RecommendationController extends AbstractController {
|
|
|
63
87
|
}
|
|
64
88
|
},
|
|
65
89
|
impression: (result) => {
|
|
90
|
+
if (!result) {
|
|
91
|
+
this.log.warn('No result provided to track.product.impression');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
66
94
|
const responseId = result.responseId;
|
|
67
|
-
if (this.events[responseId]
|
|
95
|
+
if (!this.events[responseId]) {
|
|
96
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
else if (this.events[responseId]?.product[result.id]?.impression) {
|
|
68
100
|
return;
|
|
69
101
|
}
|
|
102
|
+
const type = (['product', 'banner'].includes(result.type) ? result.type : 'product');
|
|
70
103
|
const item = {
|
|
71
|
-
type
|
|
72
|
-
uid: result.id,
|
|
73
|
-
|
|
74
|
-
|
|
104
|
+
type,
|
|
105
|
+
uid: result.id ? '' + result.id : '',
|
|
106
|
+
...(type === 'product'
|
|
107
|
+
? {
|
|
108
|
+
parentId: result.id ? '' + result.id : '',
|
|
109
|
+
sku: result.mappings.core?.sku ? '' + result.mappings.core?.sku : undefined,
|
|
110
|
+
}
|
|
111
|
+
: {}),
|
|
75
112
|
};
|
|
76
113
|
const data = {
|
|
77
114
|
tag: this.store.profile.tag,
|
|
@@ -80,12 +117,20 @@ export class RecommendationController extends AbstractController {
|
|
|
80
117
|
banners: [],
|
|
81
118
|
};
|
|
82
119
|
this.eventManager.fire('track.product.impression', { controller: this, product: result, trackEvent: data });
|
|
83
|
-
this.tracker.events.recommendations.impression({ data, siteId: this.config.globals?.siteId });
|
|
120
|
+
this.config.beacon?.enabled && this.tracker.events.recommendations.impression({ data, siteId: this.config.globals?.siteId });
|
|
84
121
|
this.events[responseId].product[result.id] = this.events[responseId].product[result.id] || {};
|
|
85
122
|
this.events[responseId].product[result.id].impression = true;
|
|
86
123
|
},
|
|
87
124
|
addToCart: (result) => {
|
|
125
|
+
if (!result) {
|
|
126
|
+
this.log.warn('No result provided to track.product.addToCart');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
88
129
|
const responseId = result.responseId;
|
|
130
|
+
if (!this.events[responseId]) {
|
|
131
|
+
this.log.warn('No responseId found in controller, ensure correct controller is used');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
89
134
|
const product = {
|
|
90
135
|
parentId: result.id,
|
|
91
136
|
uid: result.id,
|
|
@@ -99,7 +144,7 @@ export class RecommendationController extends AbstractController {
|
|
|
99
144
|
results: [product],
|
|
100
145
|
};
|
|
101
146
|
this.eventManager.fire('track.product.addToCart', { controller: this, product: result, trackEvent: data });
|
|
102
|
-
this.tracker.events.recommendations.addToCart({ data, siteId: this.config.globals?.siteId });
|
|
147
|
+
this.config.beacon?.enabled && this.tracker.events.recommendations.addToCart({ data, siteId: this.config.globals?.siteId });
|
|
103
148
|
},
|
|
104
149
|
},
|
|
105
150
|
};
|
|
@@ -155,6 +200,8 @@ export class RecommendationController extends AbstractController {
|
|
|
155
200
|
this.log.profile(afterSearchProfile);
|
|
156
201
|
// update the store
|
|
157
202
|
this.store.update(response);
|
|
203
|
+
const data = { responseId, tag: this.store.profile.tag };
|
|
204
|
+
this.config.beacon?.enabled && this.tracker.events.recommendations.render({ data, siteId: this.config.globals?.siteId });
|
|
158
205
|
const afterStoreProfile = this.profiler.create({ type: 'event', name: 'afterStore', context: params }).start();
|
|
159
206
|
try {
|
|
160
207
|
await this.eventManager.fire('afterStore', {
|
|
@@ -223,7 +270,11 @@ export class RecommendationController extends AbstractController {
|
|
|
223
270
|
}
|
|
224
271
|
};
|
|
225
272
|
this.addToCart = async (_products) => {
|
|
226
|
-
const products = typeof _products
|
|
273
|
+
const products = typeof _products?.slice == 'function' ? _products.slice() : [_products];
|
|
274
|
+
if (!_products || products.length === 0) {
|
|
275
|
+
this.log.warn('No products provided to recommendation controller.addToCart');
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
227
278
|
products.forEach((product) => {
|
|
228
279
|
this.track.product.addToCart(product);
|
|
229
280
|
});
|
|
@@ -246,15 +297,6 @@ export class RecommendationController extends AbstractController {
|
|
|
246
297
|
// deep merge config with defaults
|
|
247
298
|
this.config = deepmerge(defaultConfig, this.config);
|
|
248
299
|
this.store.setConfig(this.config);
|
|
249
|
-
this.eventManager.on('afterStore', async (search, next) => {
|
|
250
|
-
await next();
|
|
251
|
-
const controller = search.controller;
|
|
252
|
-
const responseId = search.response.responseId;
|
|
253
|
-
if (controller.store.loaded && !controller.store.error) {
|
|
254
|
-
const data = { responseId, tag: controller.store.profile.tag };
|
|
255
|
-
this.tracker.events.recommendations.render({ data, siteId: this.config.globals?.siteId });
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
300
|
// add 'afterStore' middleware
|
|
259
301
|
// this.eventManager.on('afterStore', async (recommend: AfterStoreObj, next: Next): Promise<void | boolean> => {
|
|
260
302
|
// await next();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchController.d.ts","sourceRoot":"","sources":["../../../src/Search/SearchController.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,YAAY,EAAa,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAEpG,OAAO,EAAE,eAAe,EAAuB,MAAM,UAAU,CAAC;AAEhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAc,MAAM,+BAA+B,CAAC;AAC9F,OAAO,KAAK,EACX,sBAAsB,EAGtB,kBAAkB,EAClB,gBAAgB,EAIhB,MAAM,UAAU,CAAC;AAElB,OAAO,EACN,KAAK,kBAAkB,EAYvB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchController.d.ts","sourceRoot":"","sources":["../../../src/Search/SearchController.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,YAAY,EAAa,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAEpG,OAAO,EAAE,eAAe,EAAuB,MAAM,UAAU,CAAC;AAEhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAc,MAAM,+BAA+B,CAAC;AAC9F,OAAO,KAAK,EACX,sBAAsB,EAGtB,kBAAkB,EAClB,gBAAgB,EAIhB,MAAM,UAAU,CAAC;AAElB,OAAO,EACN,KAAK,kBAAkB,EAYvB,MAAM,2BAA2B,CAAC;AAyCnC,KAAK,kBAAkB,GAAG;IACzB,MAAM,EAAE;QACP,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,mBAAmB,EAAE,0BAA0B,KAAK,IAAI,CAAC;QAChF,YAAY,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,mBAAmB,EAAE,0BAA0B,KAAK,IAAI,CAAC;QACvF,UAAU,EAAE,CAAC,mBAAmB,EAAE,0BAA0B,KAAK,IAAI,CAAC;KACtE,CAAC;IACF,OAAO,EAAE;QACR,YAAY,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;QACzD,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC;QAC/C,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;KACtC,CAAC;IACF,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC7F,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,kBAAkB;IAChD,IAAI,kBAA0B;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,sBAAsB,CAAC;IACvC,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,eAAe,CAAwC;IAC/D,OAAO,CAAC,IAAI,CAEV;IACF,OAAO,CAAC,MAAM,CAgBP;gBAGN,MAAM,EAAE,sBAAsB,EAC9B,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAC1F,OAAO,CAAC,EAAE,gBAAgB;IAiP3B,KAAK,EAAE,kBAAkB,CA4PvB;IAEF,IAAI,MAAM,IAAI,kBAAkB,CA8C/B;IAED,MAAM,QAAa,QAAQ,IAAI,CAAC,CA6N9B;IAEF,SAAS,cAAqB,OAAO,EAAE,GAAG,OAAO,KAAG,QAAQ,IAAI,CAAC,CAY/D;CACF;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,kBAAkB,GAAG,kBAAkB,CAiBxF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,MAAM,GAAG,SAAS,CAuCvG"}
|