@getlupa/client 0.14.3 → 0.15.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/components/search-results/SearchResults.vue.d.ts +6 -0
- package/dist/cjs/components/search-results/products/product-card/SearchResultsProductCard.vue.d.ts +2 -0
- package/dist/cjs/index.min.js +73 -12
- package/dist/cjs/store/modules/options.d.ts +5 -0
- package/dist/cjs/types/AnalyticsOptions.d.ts +2 -1
- package/dist/cjs/types/search-box/Common.d.ts +4 -0
- package/dist/es/components/search-results/SearchResults.vue.d.ts +6 -0
- package/dist/es/components/search-results/products/product-card/SearchResultsProductCard.vue.d.ts +2 -0
- package/dist/es/index.min.js +73 -12
- package/dist/es/store/modules/options.d.ts +5 -0
- package/dist/es/types/AnalyticsOptions.d.ts +2 -1
- package/dist/es/types/search-box/Common.d.ts +4 -0
- package/dist/iife/components/search-results/SearchResults.vue.d.ts +6 -0
- package/dist/iife/components/search-results/products/product-card/SearchResultsProductCard.vue.d.ts +2 -0
- package/dist/iife/index.min.js +1 -1
- package/dist/iife/store/modules/options.d.ts +5 -0
- package/dist/iife/types/AnalyticsOptions.d.ts +2 -1
- package/dist/iife/types/search-box/Common.d.ts +4 -0
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import { ProductGrid, SearchResultsDidYouMeanLabels, SearchResultsOptions, Searc
|
|
|
3
3
|
import { FilterGroup, PublicQuery, SearchQueryResult } from "@getlupa/client-sdk/Types";
|
|
4
4
|
import Vue from "vue";
|
|
5
5
|
import { AnalyticsEventType } from "@/types/AnalyticsOptions";
|
|
6
|
+
import { TrackableEventData } from "@/types/search-box/Common";
|
|
6
7
|
export default class SearchResults extends Vue {
|
|
7
8
|
options: SearchResultsOptions;
|
|
8
9
|
initialFilters: FilterGroup;
|
|
@@ -24,6 +25,10 @@ export default class SearchResults extends Vue {
|
|
|
24
25
|
queryKey: string;
|
|
25
26
|
results: SearchQueryResult;
|
|
26
27
|
}) => void;
|
|
28
|
+
trackEvent: ({ queryKey, data, }: {
|
|
29
|
+
queryKey: string;
|
|
30
|
+
data: TrackableEventData;
|
|
31
|
+
}) => void;
|
|
27
32
|
enhanceData: ({ result, }: {
|
|
28
33
|
result: SearchQueryResult;
|
|
29
34
|
}) => Promise<void>;
|
|
@@ -53,6 +58,7 @@ export default class SearchResults extends Vue {
|
|
|
53
58
|
}) => void;
|
|
54
59
|
mounted(): void;
|
|
55
60
|
beforeDestroy(): void;
|
|
61
|
+
trackItemListView(title: string, items?: Record<string, unknown>[]): void;
|
|
56
62
|
handleMounted(): void;
|
|
57
63
|
handleParamsChange(): void;
|
|
58
64
|
addSearchResult: (searchResult: SearchQueryResult) => SearchQueryResult;
|
package/dist/cjs/components/search-results/products/product-card/SearchResultsProductCard.vue.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DocumentElement } from "@/types/DocumentElement";
|
|
2
|
+
import { TrackingOptions } from "@/types/General";
|
|
2
3
|
import { TrackableEventData } from "@/types/search-box/Common";
|
|
3
4
|
import { BadgeOptions } from "@/types/search-results/BadgeOptions";
|
|
4
5
|
import { ResultsLayout } from "@/types/search-results/ResultsLayout";
|
|
@@ -15,6 +16,7 @@ export default class SearchResultsProductCard extends Vue {
|
|
|
15
16
|
layout: ResultsLayout;
|
|
16
17
|
searchResultsRoutingBehavior: RoutingBehavior;
|
|
17
18
|
searchResultOptions: SearchResultsOptions;
|
|
19
|
+
trackingOptions: TrackingOptions;
|
|
18
20
|
query: string;
|
|
19
21
|
trackClick: ({ queryKey, data, }: {
|
|
20
22
|
queryKey: string;
|
package/dist/cjs/index.min.js
CHANGED
|
@@ -12429,6 +12429,7 @@ let SearchBoxProduct = class SearchBoxProduct extends Vue$1 {
|
|
|
12429
12429
|
analytics: {
|
|
12430
12430
|
type: "autocomplete_product_click",
|
|
12431
12431
|
label: (_a = this.title) !== null && _a !== void 0 ? _a : this.link,
|
|
12432
|
+
items: [this.item],
|
|
12432
12433
|
},
|
|
12433
12434
|
},
|
|
12434
12435
|
});
|
|
@@ -31119,6 +31120,7 @@ let SearchBox = class SearchBox extends Vue$1 {
|
|
|
31119
31120
|
analytics: {
|
|
31120
31121
|
type: "autocomplete_product_click",
|
|
31121
31122
|
label: doc.title || doc.id,
|
|
31123
|
+
items: [doc],
|
|
31122
31124
|
},
|
|
31123
31125
|
},
|
|
31124
31126
|
});
|
|
@@ -31257,7 +31259,7 @@ __vue_render__$V._withStripped = true;
|
|
|
31257
31259
|
/* style */
|
|
31258
31260
|
const __vue_inject_styles__$V = function (inject) {
|
|
31259
31261
|
if (!inject) return
|
|
31260
|
-
inject("data-v-
|
|
31262
|
+
inject("data-v-1d0dc04c_0", { source: "\n#lupa-search-box {\n width: 100%;\n}\n.lupa-search-box-wrapper {\n position: relative;\n}\n", map: undefined, media: undefined });
|
|
31261
31263
|
|
|
31262
31264
|
};
|
|
31263
31265
|
/* scoped */
|
|
@@ -35682,9 +35684,11 @@ let SearchResultsProductCard = class SearchResultsProductCard extends Vue$1 {
|
|
|
35682
35684
|
searchQuery: this.query,
|
|
35683
35685
|
type: "itemClick",
|
|
35684
35686
|
analytics: {
|
|
35685
|
-
type: "search_product_click",
|
|
35687
|
+
type: this.query ? "search_product_click" : "select_item",
|
|
35686
35688
|
label: this.title || this.id || this.link,
|
|
35689
|
+
items: [this.product],
|
|
35687
35690
|
},
|
|
35691
|
+
options: { allowEmptySearchQuery: true },
|
|
35688
35692
|
},
|
|
35689
35693
|
});
|
|
35690
35694
|
(_b = (_a = this.searchResultOptions.callbacks) === null || _a === void 0 ? void 0 : _a.onProductClick) === null || _b === void 0 ? void 0 : _b.call(_a, {
|
|
@@ -35730,6 +35734,9 @@ __decorate([
|
|
|
35730
35734
|
__decorate([
|
|
35731
35735
|
options$7.State((o) => o.searchResultOptions)
|
|
35732
35736
|
], SearchResultsProductCard.prototype, "searchResultOptions", void 0);
|
|
35737
|
+
__decorate([
|
|
35738
|
+
options$7.State((o) => o.trackingOptions)
|
|
35739
|
+
], SearchResultsProductCard.prototype, "trackingOptions", void 0);
|
|
35733
35740
|
__decorate([
|
|
35734
35741
|
params$a.Getter("query")
|
|
35735
35742
|
], SearchResultsProductCard.prototype, "query", void 0);
|
|
@@ -36066,6 +36073,15 @@ const trackAnalyticsEvent = (data) => {
|
|
|
36066
36073
|
console.error("Unable to send an event to google analytics");
|
|
36067
36074
|
}
|
|
36068
36075
|
};
|
|
36076
|
+
const parseEcommerceData = (data, title) => {
|
|
36077
|
+
var _a, _b;
|
|
36078
|
+
return ((_a = data.analytics) === null || _a === void 0 ? void 0 : _a.items)
|
|
36079
|
+
? {
|
|
36080
|
+
item_list_name: title,
|
|
36081
|
+
items: (_b = data.analytics) === null || _b === void 0 ? void 0 : _b.items,
|
|
36082
|
+
}
|
|
36083
|
+
: undefined;
|
|
36084
|
+
};
|
|
36069
36085
|
const sendUaAnalyticsEvent = (data, options) => {
|
|
36070
36086
|
var _a, _b, _c, _d;
|
|
36071
36087
|
const ga = window.ga;
|
|
@@ -36076,34 +36092,47 @@ const sendUaAnalyticsEvent = (data, options) => {
|
|
|
36076
36092
|
sendGa("send", "event", options.parentEventName, (_b = (_a = data.analytics) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "", (_d = (_c = data.analytics) === null || _c === void 0 ? void 0 : _c.label) !== null && _d !== void 0 ? _d : "");
|
|
36077
36093
|
};
|
|
36078
36094
|
const sendGa4AnalyticsEvent = (data, options) => {
|
|
36079
|
-
var _a, _b, _c, _d;
|
|
36095
|
+
var _a, _b, _c, _d, _e;
|
|
36080
36096
|
if (!window || !window.dataLayer) {
|
|
36081
36097
|
console.error("dataLayer object not found.");
|
|
36082
36098
|
return;
|
|
36083
36099
|
}
|
|
36084
36100
|
const sendItemTitle = data.searchQuery !== ((_a = data.analytics) === null || _a === void 0 ? void 0 : _a.label);
|
|
36101
|
+
const title = sendItemTitle ? (_b = data.analytics) === null || _b === void 0 ? void 0 : _b.label : undefined;
|
|
36085
36102
|
const params = {
|
|
36086
36103
|
search_text: data.searchQuery,
|
|
36087
|
-
item_title: sendItemTitle ? (
|
|
36104
|
+
item_title: sendItemTitle ? (_c = data.analytics) === null || _c === void 0 ? void 0 : _c.label : undefined,
|
|
36105
|
+
ecommerce: parseEcommerceData(data, title),
|
|
36088
36106
|
};
|
|
36089
|
-
window.dataLayer.push(Object.assign({ event: (
|
|
36107
|
+
window.dataLayer.push(Object.assign({ event: (_e = (_d = data.analytics) === null || _d === void 0 ? void 0 : _d.type) !== null && _e !== void 0 ? _e : options.parentEventName }, params));
|
|
36090
36108
|
};
|
|
36091
36109
|
const processDebugEvent = (data) => {
|
|
36092
36110
|
var _a, _b, _c;
|
|
36093
36111
|
const sendItemTitle = data.searchQuery !== ((_a = data.analytics) === null || _a === void 0 ? void 0 : _a.label);
|
|
36112
|
+
const title = sendItemTitle ? (_b = data.analytics) === null || _b === void 0 ? void 0 : _b.label : undefined;
|
|
36094
36113
|
const params = {
|
|
36095
|
-
event: (
|
|
36114
|
+
event: (_c = data.analytics) === null || _c === void 0 ? void 0 : _c.type,
|
|
36096
36115
|
search_text: data.searchQuery,
|
|
36097
|
-
item_title:
|
|
36116
|
+
item_title: title,
|
|
36117
|
+
ecommerce: parseEcommerceData(data, title),
|
|
36098
36118
|
};
|
|
36099
36119
|
console.debug("Analytics debug event:", params);
|
|
36100
36120
|
};
|
|
36101
36121
|
const track = (queryKey, data = {}, options) => {
|
|
36102
|
-
|
|
36122
|
+
var _a;
|
|
36123
|
+
if (!isTrackingEnabled()) {
|
|
36124
|
+
return;
|
|
36125
|
+
}
|
|
36126
|
+
const hasSearchQuery = data.searchQuery;
|
|
36127
|
+
if (!hasSearchQuery && !((_a = data.options) === null || _a === void 0 ? void 0 : _a.allowEmptySearchQuery)) {
|
|
36103
36128
|
return;
|
|
36104
36129
|
}
|
|
36105
|
-
trackLupaEvent(queryKey, data, options);
|
|
36106
36130
|
trackAnalyticsEvent(data);
|
|
36131
|
+
// Lupa events are only tracked if search query is set
|
|
36132
|
+
if (!hasSearchQuery) {
|
|
36133
|
+
return;
|
|
36134
|
+
}
|
|
36135
|
+
trackLupaEvent(queryKey, data, options);
|
|
36107
36136
|
};
|
|
36108
36137
|
|
|
36109
36138
|
const params$9 = namespace("params");
|
|
@@ -38456,11 +38485,25 @@ let SearchResults = class SearchResults extends Vue$1 {
|
|
|
38456
38485
|
beforeDestroy() {
|
|
38457
38486
|
window.removeEventListener("resize", this.handleResize);
|
|
38458
38487
|
}
|
|
38488
|
+
trackItemListView(title, items = []) {
|
|
38489
|
+
this.trackEvent({
|
|
38490
|
+
queryKey: this.options.queryKey,
|
|
38491
|
+
data: {
|
|
38492
|
+
analytics: {
|
|
38493
|
+
type: "view_item_list",
|
|
38494
|
+
label: title,
|
|
38495
|
+
items,
|
|
38496
|
+
},
|
|
38497
|
+
options: { allowEmptySearchQuery: true },
|
|
38498
|
+
},
|
|
38499
|
+
});
|
|
38500
|
+
}
|
|
38459
38501
|
handleMounted() {
|
|
38460
38502
|
var _a;
|
|
38461
38503
|
this.handleResize();
|
|
38462
38504
|
if (this.isProductList) {
|
|
38463
|
-
|
|
38505
|
+
const pageTitle = this.options.labels.htmlTitleTemplate;
|
|
38506
|
+
setDocumentTitle(pageTitle, "");
|
|
38464
38507
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38465
38508
|
(_a = this.$refs.searchResultsFilters) === null || _a === void 0 ? void 0 : _a.fetch();
|
|
38466
38509
|
}
|
|
@@ -38531,6 +38574,7 @@ let SearchResults = class SearchResults extends Vue$1 {
|
|
|
38531
38574
|
if (!hasResults) {
|
|
38532
38575
|
return;
|
|
38533
38576
|
}
|
|
38577
|
+
this.trackItemListView(this.options.labels.htmlTitleTemplate, results.items);
|
|
38534
38578
|
yield this.enhanceData({ result: results });
|
|
38535
38579
|
});
|
|
38536
38580
|
}
|
|
@@ -38568,6 +38612,9 @@ __decorate([
|
|
|
38568
38612
|
__decorate([
|
|
38569
38613
|
tracking$2.Action("trackResults")
|
|
38570
38614
|
], SearchResults.prototype, "trackResults", void 0);
|
|
38615
|
+
__decorate([
|
|
38616
|
+
tracking$2.Action("track")
|
|
38617
|
+
], SearchResults.prototype, "trackEvent", void 0);
|
|
38571
38618
|
__decorate([
|
|
38572
38619
|
dynamicData$1.Action("enhanceSearchResultsWithDynamicData")
|
|
38573
38620
|
], SearchResults.prototype, "enhanceData", void 0);
|
|
@@ -40368,6 +40415,7 @@ let OptionsModule = class OptionsModule extends VuexModule {
|
|
|
40368
40415
|
super(...arguments);
|
|
40369
40416
|
this.searchBoxOptions = DEFAULT_SEARCH_BOX_OPTIONS;
|
|
40370
40417
|
this.searchResultOptions = DEFAULT_OPTIONS_RESULTS;
|
|
40418
|
+
this.trackingOptions = {};
|
|
40371
40419
|
this.searchResultInitialFilters = {};
|
|
40372
40420
|
}
|
|
40373
40421
|
get envOptions() {
|
|
@@ -40416,6 +40464,9 @@ let OptionsModule = class OptionsModule extends VuexModule {
|
|
|
40416
40464
|
setSearchBoxOptions({ options }) {
|
|
40417
40465
|
this.searchBoxOptions = options;
|
|
40418
40466
|
}
|
|
40467
|
+
setTrackingOptions({ options }) {
|
|
40468
|
+
this.trackingOptions = options !== null && options !== void 0 ? options : {};
|
|
40469
|
+
}
|
|
40419
40470
|
setSearchResultOptions({ options }) {
|
|
40420
40471
|
this.searchResultOptions = options;
|
|
40421
40472
|
}
|
|
@@ -40426,6 +40477,9 @@ let OptionsModule = class OptionsModule extends VuexModule {
|
|
|
40426
40477
|
__decorate([
|
|
40427
40478
|
Mutation
|
|
40428
40479
|
], OptionsModule.prototype, "setSearchBoxOptions", null);
|
|
40480
|
+
__decorate([
|
|
40481
|
+
Mutation
|
|
40482
|
+
], OptionsModule.prototype, "setTrackingOptions", null);
|
|
40429
40483
|
__decorate([
|
|
40430
40484
|
Mutation
|
|
40431
40485
|
], OptionsModule.prototype, "setSearchResultOptions", null);
|
|
@@ -40470,9 +40524,15 @@ let TrackingModule = class TrackingModule extends VuexModule {
|
|
|
40470
40524
|
}
|
|
40471
40525
|
}
|
|
40472
40526
|
track({ queryKey, data, }) {
|
|
40473
|
-
var _a;
|
|
40527
|
+
var _a, _b, _c, _d, _e;
|
|
40474
40528
|
const options = (_a = this.context.rootGetters["options/envOptions"]) !== null && _a !== void 0 ? _a : {};
|
|
40475
|
-
|
|
40529
|
+
const trackingOptions = (_b = this.context.rootState["options"].trackingOptions) !== null && _b !== void 0 ? _b : {};
|
|
40530
|
+
const items = (_d = (_c = data.analytics) === null || _c === void 0 ? void 0 : _c.items) !== null && _d !== void 0 ? _d : [];
|
|
40531
|
+
const mappedItems = ((_e = trackingOptions.analytics) === null || _e === void 0 ? void 0 : _e.itemMap)
|
|
40532
|
+
? items.map(trackingOptions.analytics.itemMap)
|
|
40533
|
+
: items;
|
|
40534
|
+
track(queryKey, Object.assign(Object.assign({}, data), { analytics: data.analytics
|
|
40535
|
+
? Object.assign(Object.assign({}, data.analytics), { items: mappedItems }) : undefined }), options);
|
|
40476
40536
|
}
|
|
40477
40537
|
};
|
|
40478
40538
|
__decorate([
|
|
@@ -40647,6 +40707,7 @@ const app = {
|
|
|
40647
40707
|
};
|
|
40648
40708
|
const tracking = (options) => {
|
|
40649
40709
|
initTracking(options);
|
|
40710
|
+
store.commit("options/setTrackingOptions", { options });
|
|
40650
40711
|
};
|
|
40651
40712
|
const applySearchBox = (options, mountOptions) => {
|
|
40652
40713
|
const existingInstance = app.box[options.inputSelector];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TrackingOptions } from "@/types/General";
|
|
1
2
|
import { SearchBoxOptions } from "@/types/search-box/SearchBoxOptions";
|
|
2
3
|
import { RoutingBehavior } from "@/types/search-results/RoutingBehavior";
|
|
3
4
|
import { SearchResultsOptions } from "@/types/search-results/SearchResultsOptions";
|
|
@@ -6,6 +7,7 @@ import { VuexModule } from "vuex-module-decorators";
|
|
|
6
7
|
export default class OptionsModule extends VuexModule {
|
|
7
8
|
searchBoxOptions: SearchBoxOptions;
|
|
8
9
|
searchResultOptions: SearchResultsOptions;
|
|
10
|
+
trackingOptions: TrackingOptions;
|
|
9
11
|
searchResultInitialFilters: FilterGroup;
|
|
10
12
|
get envOptions(): Options;
|
|
11
13
|
get classMap(): Record<string, string>;
|
|
@@ -17,6 +19,9 @@ export default class OptionsModule extends VuexModule {
|
|
|
17
19
|
setSearchBoxOptions({ options }: {
|
|
18
20
|
options: SearchBoxOptions;
|
|
19
21
|
}): void;
|
|
22
|
+
setTrackingOptions({ options }: {
|
|
23
|
+
options: TrackingOptions;
|
|
24
|
+
}): void;
|
|
20
25
|
setSearchResultOptions({ options }: {
|
|
21
26
|
options: SearchResultsOptions;
|
|
22
27
|
}): void;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export declare const PARENT_EVENT_NAME = "GetLupa";
|
|
2
|
-
export declare type AnalyticsEventType = "search_query" | "search_form_submit" | "autocomplete_suggestion_click" | "autocomplete_product_click" | "search_product_click" | "search_zero_results" | "search_filters" | "search_add_to_cart";
|
|
2
|
+
export declare type AnalyticsEventType = "search_query" | "search_form_submit" | "autocomplete_suggestion_click" | "autocomplete_product_click" | "search_product_click" | "search_zero_results" | "search_filters" | "search_add_to_cart" | "view_item_list" | "select_item";
|
|
3
3
|
export declare type AnalyticsOptions = {
|
|
4
4
|
type: "ua" | "ga4" | "debug";
|
|
5
5
|
enabled: boolean;
|
|
6
6
|
parentEventName: string;
|
|
7
7
|
ignoreEvents?: AnalyticsEventType[];
|
|
8
|
+
itemMap?: (item: Record<string, unknown>) => Record<string, unknown>;
|
|
8
9
|
};
|
|
@@ -34,6 +34,10 @@ export declare type TrackableEventData = {
|
|
|
34
34
|
analytics?: {
|
|
35
35
|
type: AnalyticsEventType;
|
|
36
36
|
label: string;
|
|
37
|
+
items?: Record<string, unknown>[];
|
|
38
|
+
};
|
|
39
|
+
options?: {
|
|
40
|
+
allowEmptySearchQuery: boolean;
|
|
37
41
|
};
|
|
38
42
|
};
|
|
39
43
|
export declare type HighlightedDocInfo = {
|
|
@@ -3,6 +3,7 @@ import { ProductGrid, SearchResultsDidYouMeanLabels, SearchResultsOptions, Searc
|
|
|
3
3
|
import { FilterGroup, PublicQuery, SearchQueryResult } from "@getlupa/client-sdk/Types";
|
|
4
4
|
import Vue from "vue";
|
|
5
5
|
import { AnalyticsEventType } from "@/types/AnalyticsOptions";
|
|
6
|
+
import { TrackableEventData } from "@/types/search-box/Common";
|
|
6
7
|
export default class SearchResults extends Vue {
|
|
7
8
|
options: SearchResultsOptions;
|
|
8
9
|
initialFilters: FilterGroup;
|
|
@@ -24,6 +25,10 @@ export default class SearchResults extends Vue {
|
|
|
24
25
|
queryKey: string;
|
|
25
26
|
results: SearchQueryResult;
|
|
26
27
|
}) => void;
|
|
28
|
+
trackEvent: ({ queryKey, data, }: {
|
|
29
|
+
queryKey: string;
|
|
30
|
+
data: TrackableEventData;
|
|
31
|
+
}) => void;
|
|
27
32
|
enhanceData: ({ result, }: {
|
|
28
33
|
result: SearchQueryResult;
|
|
29
34
|
}) => Promise<void>;
|
|
@@ -53,6 +58,7 @@ export default class SearchResults extends Vue {
|
|
|
53
58
|
}) => void;
|
|
54
59
|
mounted(): void;
|
|
55
60
|
beforeDestroy(): void;
|
|
61
|
+
trackItemListView(title: string, items?: Record<string, unknown>[]): void;
|
|
56
62
|
handleMounted(): void;
|
|
57
63
|
handleParamsChange(): void;
|
|
58
64
|
addSearchResult: (searchResult: SearchQueryResult) => SearchQueryResult;
|
package/dist/es/components/search-results/products/product-card/SearchResultsProductCard.vue.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DocumentElement } from "@/types/DocumentElement";
|
|
2
|
+
import { TrackingOptions } from "@/types/General";
|
|
2
3
|
import { TrackableEventData } from "@/types/search-box/Common";
|
|
3
4
|
import { BadgeOptions } from "@/types/search-results/BadgeOptions";
|
|
4
5
|
import { ResultsLayout } from "@/types/search-results/ResultsLayout";
|
|
@@ -15,6 +16,7 @@ export default class SearchResultsProductCard extends Vue {
|
|
|
15
16
|
layout: ResultsLayout;
|
|
16
17
|
searchResultsRoutingBehavior: RoutingBehavior;
|
|
17
18
|
searchResultOptions: SearchResultsOptions;
|
|
19
|
+
trackingOptions: TrackingOptions;
|
|
18
20
|
query: string;
|
|
19
21
|
trackClick: ({ queryKey, data, }: {
|
|
20
22
|
queryKey: string;
|
package/dist/es/index.min.js
CHANGED
|
@@ -12425,6 +12425,7 @@ let SearchBoxProduct = class SearchBoxProduct extends Vue$1 {
|
|
|
12425
12425
|
analytics: {
|
|
12426
12426
|
type: "autocomplete_product_click",
|
|
12427
12427
|
label: (_a = this.title) !== null && _a !== void 0 ? _a : this.link,
|
|
12428
|
+
items: [this.item],
|
|
12428
12429
|
},
|
|
12429
12430
|
},
|
|
12430
12431
|
});
|
|
@@ -31115,6 +31116,7 @@ let SearchBox = class SearchBox extends Vue$1 {
|
|
|
31115
31116
|
analytics: {
|
|
31116
31117
|
type: "autocomplete_product_click",
|
|
31117
31118
|
label: doc.title || doc.id,
|
|
31119
|
+
items: [doc],
|
|
31118
31120
|
},
|
|
31119
31121
|
},
|
|
31120
31122
|
});
|
|
@@ -31253,7 +31255,7 @@ __vue_render__$V._withStripped = true;
|
|
|
31253
31255
|
/* style */
|
|
31254
31256
|
const __vue_inject_styles__$V = function (inject) {
|
|
31255
31257
|
if (!inject) return
|
|
31256
|
-
inject("data-v-
|
|
31258
|
+
inject("data-v-1d0dc04c_0", { source: "\n#lupa-search-box {\n width: 100%;\n}\n.lupa-search-box-wrapper {\n position: relative;\n}\n", map: undefined, media: undefined });
|
|
31257
31259
|
|
|
31258
31260
|
};
|
|
31259
31261
|
/* scoped */
|
|
@@ -35678,9 +35680,11 @@ let SearchResultsProductCard = class SearchResultsProductCard extends Vue$1 {
|
|
|
35678
35680
|
searchQuery: this.query,
|
|
35679
35681
|
type: "itemClick",
|
|
35680
35682
|
analytics: {
|
|
35681
|
-
type: "search_product_click",
|
|
35683
|
+
type: this.query ? "search_product_click" : "select_item",
|
|
35682
35684
|
label: this.title || this.id || this.link,
|
|
35685
|
+
items: [this.product],
|
|
35683
35686
|
},
|
|
35687
|
+
options: { allowEmptySearchQuery: true },
|
|
35684
35688
|
},
|
|
35685
35689
|
});
|
|
35686
35690
|
(_b = (_a = this.searchResultOptions.callbacks) === null || _a === void 0 ? void 0 : _a.onProductClick) === null || _b === void 0 ? void 0 : _b.call(_a, {
|
|
@@ -35726,6 +35730,9 @@ __decorate([
|
|
|
35726
35730
|
__decorate([
|
|
35727
35731
|
options$7.State((o) => o.searchResultOptions)
|
|
35728
35732
|
], SearchResultsProductCard.prototype, "searchResultOptions", void 0);
|
|
35733
|
+
__decorate([
|
|
35734
|
+
options$7.State((o) => o.trackingOptions)
|
|
35735
|
+
], SearchResultsProductCard.prototype, "trackingOptions", void 0);
|
|
35729
35736
|
__decorate([
|
|
35730
35737
|
params$a.Getter("query")
|
|
35731
35738
|
], SearchResultsProductCard.prototype, "query", void 0);
|
|
@@ -36062,6 +36069,15 @@ const trackAnalyticsEvent = (data) => {
|
|
|
36062
36069
|
console.error("Unable to send an event to google analytics");
|
|
36063
36070
|
}
|
|
36064
36071
|
};
|
|
36072
|
+
const parseEcommerceData = (data, title) => {
|
|
36073
|
+
var _a, _b;
|
|
36074
|
+
return ((_a = data.analytics) === null || _a === void 0 ? void 0 : _a.items)
|
|
36075
|
+
? {
|
|
36076
|
+
item_list_name: title,
|
|
36077
|
+
items: (_b = data.analytics) === null || _b === void 0 ? void 0 : _b.items,
|
|
36078
|
+
}
|
|
36079
|
+
: undefined;
|
|
36080
|
+
};
|
|
36065
36081
|
const sendUaAnalyticsEvent = (data, options) => {
|
|
36066
36082
|
var _a, _b, _c, _d;
|
|
36067
36083
|
const ga = window.ga;
|
|
@@ -36072,34 +36088,47 @@ const sendUaAnalyticsEvent = (data, options) => {
|
|
|
36072
36088
|
sendGa("send", "event", options.parentEventName, (_b = (_a = data.analytics) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "", (_d = (_c = data.analytics) === null || _c === void 0 ? void 0 : _c.label) !== null && _d !== void 0 ? _d : "");
|
|
36073
36089
|
};
|
|
36074
36090
|
const sendGa4AnalyticsEvent = (data, options) => {
|
|
36075
|
-
var _a, _b, _c, _d;
|
|
36091
|
+
var _a, _b, _c, _d, _e;
|
|
36076
36092
|
if (!window || !window.dataLayer) {
|
|
36077
36093
|
console.error("dataLayer object not found.");
|
|
36078
36094
|
return;
|
|
36079
36095
|
}
|
|
36080
36096
|
const sendItemTitle = data.searchQuery !== ((_a = data.analytics) === null || _a === void 0 ? void 0 : _a.label);
|
|
36097
|
+
const title = sendItemTitle ? (_b = data.analytics) === null || _b === void 0 ? void 0 : _b.label : undefined;
|
|
36081
36098
|
const params = {
|
|
36082
36099
|
search_text: data.searchQuery,
|
|
36083
|
-
item_title: sendItemTitle ? (
|
|
36100
|
+
item_title: sendItemTitle ? (_c = data.analytics) === null || _c === void 0 ? void 0 : _c.label : undefined,
|
|
36101
|
+
ecommerce: parseEcommerceData(data, title),
|
|
36084
36102
|
};
|
|
36085
|
-
window.dataLayer.push(Object.assign({ event: (
|
|
36103
|
+
window.dataLayer.push(Object.assign({ event: (_e = (_d = data.analytics) === null || _d === void 0 ? void 0 : _d.type) !== null && _e !== void 0 ? _e : options.parentEventName }, params));
|
|
36086
36104
|
};
|
|
36087
36105
|
const processDebugEvent = (data) => {
|
|
36088
36106
|
var _a, _b, _c;
|
|
36089
36107
|
const sendItemTitle = data.searchQuery !== ((_a = data.analytics) === null || _a === void 0 ? void 0 : _a.label);
|
|
36108
|
+
const title = sendItemTitle ? (_b = data.analytics) === null || _b === void 0 ? void 0 : _b.label : undefined;
|
|
36090
36109
|
const params = {
|
|
36091
|
-
event: (
|
|
36110
|
+
event: (_c = data.analytics) === null || _c === void 0 ? void 0 : _c.type,
|
|
36092
36111
|
search_text: data.searchQuery,
|
|
36093
|
-
item_title:
|
|
36112
|
+
item_title: title,
|
|
36113
|
+
ecommerce: parseEcommerceData(data, title),
|
|
36094
36114
|
};
|
|
36095
36115
|
console.debug("Analytics debug event:", params);
|
|
36096
36116
|
};
|
|
36097
36117
|
const track = (queryKey, data = {}, options) => {
|
|
36098
|
-
|
|
36118
|
+
var _a;
|
|
36119
|
+
if (!isTrackingEnabled()) {
|
|
36120
|
+
return;
|
|
36121
|
+
}
|
|
36122
|
+
const hasSearchQuery = data.searchQuery;
|
|
36123
|
+
if (!hasSearchQuery && !((_a = data.options) === null || _a === void 0 ? void 0 : _a.allowEmptySearchQuery)) {
|
|
36099
36124
|
return;
|
|
36100
36125
|
}
|
|
36101
|
-
trackLupaEvent(queryKey, data, options);
|
|
36102
36126
|
trackAnalyticsEvent(data);
|
|
36127
|
+
// Lupa events are only tracked if search query is set
|
|
36128
|
+
if (!hasSearchQuery) {
|
|
36129
|
+
return;
|
|
36130
|
+
}
|
|
36131
|
+
trackLupaEvent(queryKey, data, options);
|
|
36103
36132
|
};
|
|
36104
36133
|
|
|
36105
36134
|
const params$9 = namespace("params");
|
|
@@ -38452,11 +38481,25 @@ let SearchResults = class SearchResults extends Vue$1 {
|
|
|
38452
38481
|
beforeDestroy() {
|
|
38453
38482
|
window.removeEventListener("resize", this.handleResize);
|
|
38454
38483
|
}
|
|
38484
|
+
trackItemListView(title, items = []) {
|
|
38485
|
+
this.trackEvent({
|
|
38486
|
+
queryKey: this.options.queryKey,
|
|
38487
|
+
data: {
|
|
38488
|
+
analytics: {
|
|
38489
|
+
type: "view_item_list",
|
|
38490
|
+
label: title,
|
|
38491
|
+
items,
|
|
38492
|
+
},
|
|
38493
|
+
options: { allowEmptySearchQuery: true },
|
|
38494
|
+
},
|
|
38495
|
+
});
|
|
38496
|
+
}
|
|
38455
38497
|
handleMounted() {
|
|
38456
38498
|
var _a;
|
|
38457
38499
|
this.handleResize();
|
|
38458
38500
|
if (this.isProductList) {
|
|
38459
|
-
|
|
38501
|
+
const pageTitle = this.options.labels.htmlTitleTemplate;
|
|
38502
|
+
setDocumentTitle(pageTitle, "");
|
|
38460
38503
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38461
38504
|
(_a = this.$refs.searchResultsFilters) === null || _a === void 0 ? void 0 : _a.fetch();
|
|
38462
38505
|
}
|
|
@@ -38527,6 +38570,7 @@ let SearchResults = class SearchResults extends Vue$1 {
|
|
|
38527
38570
|
if (!hasResults) {
|
|
38528
38571
|
return;
|
|
38529
38572
|
}
|
|
38573
|
+
this.trackItemListView(this.options.labels.htmlTitleTemplate, results.items);
|
|
38530
38574
|
yield this.enhanceData({ result: results });
|
|
38531
38575
|
});
|
|
38532
38576
|
}
|
|
@@ -38564,6 +38608,9 @@ __decorate([
|
|
|
38564
38608
|
__decorate([
|
|
38565
38609
|
tracking$2.Action("trackResults")
|
|
38566
38610
|
], SearchResults.prototype, "trackResults", void 0);
|
|
38611
|
+
__decorate([
|
|
38612
|
+
tracking$2.Action("track")
|
|
38613
|
+
], SearchResults.prototype, "trackEvent", void 0);
|
|
38567
38614
|
__decorate([
|
|
38568
38615
|
dynamicData$1.Action("enhanceSearchResultsWithDynamicData")
|
|
38569
38616
|
], SearchResults.prototype, "enhanceData", void 0);
|
|
@@ -40364,6 +40411,7 @@ let OptionsModule = class OptionsModule extends VuexModule {
|
|
|
40364
40411
|
super(...arguments);
|
|
40365
40412
|
this.searchBoxOptions = DEFAULT_SEARCH_BOX_OPTIONS;
|
|
40366
40413
|
this.searchResultOptions = DEFAULT_OPTIONS_RESULTS;
|
|
40414
|
+
this.trackingOptions = {};
|
|
40367
40415
|
this.searchResultInitialFilters = {};
|
|
40368
40416
|
}
|
|
40369
40417
|
get envOptions() {
|
|
@@ -40412,6 +40460,9 @@ let OptionsModule = class OptionsModule extends VuexModule {
|
|
|
40412
40460
|
setSearchBoxOptions({ options }) {
|
|
40413
40461
|
this.searchBoxOptions = options;
|
|
40414
40462
|
}
|
|
40463
|
+
setTrackingOptions({ options }) {
|
|
40464
|
+
this.trackingOptions = options !== null && options !== void 0 ? options : {};
|
|
40465
|
+
}
|
|
40415
40466
|
setSearchResultOptions({ options }) {
|
|
40416
40467
|
this.searchResultOptions = options;
|
|
40417
40468
|
}
|
|
@@ -40422,6 +40473,9 @@ let OptionsModule = class OptionsModule extends VuexModule {
|
|
|
40422
40473
|
__decorate([
|
|
40423
40474
|
Mutation
|
|
40424
40475
|
], OptionsModule.prototype, "setSearchBoxOptions", null);
|
|
40476
|
+
__decorate([
|
|
40477
|
+
Mutation
|
|
40478
|
+
], OptionsModule.prototype, "setTrackingOptions", null);
|
|
40425
40479
|
__decorate([
|
|
40426
40480
|
Mutation
|
|
40427
40481
|
], OptionsModule.prototype, "setSearchResultOptions", null);
|
|
@@ -40466,9 +40520,15 @@ let TrackingModule = class TrackingModule extends VuexModule {
|
|
|
40466
40520
|
}
|
|
40467
40521
|
}
|
|
40468
40522
|
track({ queryKey, data, }) {
|
|
40469
|
-
var _a;
|
|
40523
|
+
var _a, _b, _c, _d, _e;
|
|
40470
40524
|
const options = (_a = this.context.rootGetters["options/envOptions"]) !== null && _a !== void 0 ? _a : {};
|
|
40471
|
-
|
|
40525
|
+
const trackingOptions = (_b = this.context.rootState["options"].trackingOptions) !== null && _b !== void 0 ? _b : {};
|
|
40526
|
+
const items = (_d = (_c = data.analytics) === null || _c === void 0 ? void 0 : _c.items) !== null && _d !== void 0 ? _d : [];
|
|
40527
|
+
const mappedItems = ((_e = trackingOptions.analytics) === null || _e === void 0 ? void 0 : _e.itemMap)
|
|
40528
|
+
? items.map(trackingOptions.analytics.itemMap)
|
|
40529
|
+
: items;
|
|
40530
|
+
track(queryKey, Object.assign(Object.assign({}, data), { analytics: data.analytics
|
|
40531
|
+
? Object.assign(Object.assign({}, data.analytics), { items: mappedItems }) : undefined }), options);
|
|
40472
40532
|
}
|
|
40473
40533
|
};
|
|
40474
40534
|
__decorate([
|
|
@@ -40643,6 +40703,7 @@ const app = {
|
|
|
40643
40703
|
};
|
|
40644
40704
|
const tracking = (options) => {
|
|
40645
40705
|
initTracking(options);
|
|
40706
|
+
store.commit("options/setTrackingOptions", { options });
|
|
40646
40707
|
};
|
|
40647
40708
|
const applySearchBox = (options, mountOptions) => {
|
|
40648
40709
|
const existingInstance = app.box[options.inputSelector];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TrackingOptions } from "@/types/General";
|
|
1
2
|
import { SearchBoxOptions } from "@/types/search-box/SearchBoxOptions";
|
|
2
3
|
import { RoutingBehavior } from "@/types/search-results/RoutingBehavior";
|
|
3
4
|
import { SearchResultsOptions } from "@/types/search-results/SearchResultsOptions";
|
|
@@ -6,6 +7,7 @@ import { VuexModule } from "vuex-module-decorators";
|
|
|
6
7
|
export default class OptionsModule extends VuexModule {
|
|
7
8
|
searchBoxOptions: SearchBoxOptions;
|
|
8
9
|
searchResultOptions: SearchResultsOptions;
|
|
10
|
+
trackingOptions: TrackingOptions;
|
|
9
11
|
searchResultInitialFilters: FilterGroup;
|
|
10
12
|
get envOptions(): Options;
|
|
11
13
|
get classMap(): Record<string, string>;
|
|
@@ -17,6 +19,9 @@ export default class OptionsModule extends VuexModule {
|
|
|
17
19
|
setSearchBoxOptions({ options }: {
|
|
18
20
|
options: SearchBoxOptions;
|
|
19
21
|
}): void;
|
|
22
|
+
setTrackingOptions({ options }: {
|
|
23
|
+
options: TrackingOptions;
|
|
24
|
+
}): void;
|
|
20
25
|
setSearchResultOptions({ options }: {
|
|
21
26
|
options: SearchResultsOptions;
|
|
22
27
|
}): void;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export declare const PARENT_EVENT_NAME = "GetLupa";
|
|
2
|
-
export declare type AnalyticsEventType = "search_query" | "search_form_submit" | "autocomplete_suggestion_click" | "autocomplete_product_click" | "search_product_click" | "search_zero_results" | "search_filters" | "search_add_to_cart";
|
|
2
|
+
export declare type AnalyticsEventType = "search_query" | "search_form_submit" | "autocomplete_suggestion_click" | "autocomplete_product_click" | "search_product_click" | "search_zero_results" | "search_filters" | "search_add_to_cart" | "view_item_list" | "select_item";
|
|
3
3
|
export declare type AnalyticsOptions = {
|
|
4
4
|
type: "ua" | "ga4" | "debug";
|
|
5
5
|
enabled: boolean;
|
|
6
6
|
parentEventName: string;
|
|
7
7
|
ignoreEvents?: AnalyticsEventType[];
|
|
8
|
+
itemMap?: (item: Record<string, unknown>) => Record<string, unknown>;
|
|
8
9
|
};
|
|
@@ -34,6 +34,10 @@ export declare type TrackableEventData = {
|
|
|
34
34
|
analytics?: {
|
|
35
35
|
type: AnalyticsEventType;
|
|
36
36
|
label: string;
|
|
37
|
+
items?: Record<string, unknown>[];
|
|
38
|
+
};
|
|
39
|
+
options?: {
|
|
40
|
+
allowEmptySearchQuery: boolean;
|
|
37
41
|
};
|
|
38
42
|
};
|
|
39
43
|
export declare type HighlightedDocInfo = {
|
|
@@ -3,6 +3,7 @@ import { ProductGrid, SearchResultsDidYouMeanLabels, SearchResultsOptions, Searc
|
|
|
3
3
|
import { FilterGroup, PublicQuery, SearchQueryResult } from "@getlupa/client-sdk/Types";
|
|
4
4
|
import Vue from "vue";
|
|
5
5
|
import { AnalyticsEventType } from "@/types/AnalyticsOptions";
|
|
6
|
+
import { TrackableEventData } from "@/types/search-box/Common";
|
|
6
7
|
export default class SearchResults extends Vue {
|
|
7
8
|
options: SearchResultsOptions;
|
|
8
9
|
initialFilters: FilterGroup;
|
|
@@ -24,6 +25,10 @@ export default class SearchResults extends Vue {
|
|
|
24
25
|
queryKey: string;
|
|
25
26
|
results: SearchQueryResult;
|
|
26
27
|
}) => void;
|
|
28
|
+
trackEvent: ({ queryKey, data, }: {
|
|
29
|
+
queryKey: string;
|
|
30
|
+
data: TrackableEventData;
|
|
31
|
+
}) => void;
|
|
27
32
|
enhanceData: ({ result, }: {
|
|
28
33
|
result: SearchQueryResult;
|
|
29
34
|
}) => Promise<void>;
|
|
@@ -53,6 +58,7 @@ export default class SearchResults extends Vue {
|
|
|
53
58
|
}) => void;
|
|
54
59
|
mounted(): void;
|
|
55
60
|
beforeDestroy(): void;
|
|
61
|
+
trackItemListView(title: string, items?: Record<string, unknown>[]): void;
|
|
56
62
|
handleMounted(): void;
|
|
57
63
|
handleParamsChange(): void;
|
|
58
64
|
addSearchResult: (searchResult: SearchQueryResult) => SearchQueryResult;
|
package/dist/iife/components/search-results/products/product-card/SearchResultsProductCard.vue.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DocumentElement } from "@/types/DocumentElement";
|
|
2
|
+
import { TrackingOptions } from "@/types/General";
|
|
2
3
|
import { TrackableEventData } from "@/types/search-box/Common";
|
|
3
4
|
import { BadgeOptions } from "@/types/search-results/BadgeOptions";
|
|
4
5
|
import { ResultsLayout } from "@/types/search-results/ResultsLayout";
|
|
@@ -15,6 +16,7 @@ export default class SearchResultsProductCard extends Vue {
|
|
|
15
16
|
layout: ResultsLayout;
|
|
16
17
|
searchResultsRoutingBehavior: RoutingBehavior;
|
|
17
18
|
searchResultOptions: SearchResultsOptions;
|
|
19
|
+
trackingOptions: TrackingOptions;
|
|
18
20
|
query: string;
|
|
19
21
|
trackClick: ({ queryKey, data, }: {
|
|
20
22
|
queryKey: string;
|