@blotoutio/providers-shop-gpt-sdk 1.11.3 → 1.11.5

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.
Files changed (4) hide show
  1. package/index.cjs.js +295 -130
  2. package/index.js +295 -130
  3. package/index.mjs +295 -130
  4. package/package.json +1 -1
package/index.cjs.js CHANGED
@@ -376,6 +376,8 @@ const createDisabled = () => ({
376
376
  groupName: '',
377
377
  isEnabled: false,
378
378
  });
379
+ // userId => 92ae5ac6-b47c-4444-923f-87d98b7e1fac-1743927514247
380
+ // sample => 92ae5ac6
379
381
  const createABTest = ({ userId }) => {
380
382
  const [sample] = userId.split('-');
381
383
  const segment = parseInt(sample, 16) % 2;
@@ -411,6 +413,7 @@ const createExperiment = (props) => {
411
413
  /** Action length should not exceed 42 */
412
414
  const uiActions = new Set([
413
415
  'shopGPTInitialized',
416
+ 'shopGPTLoaded',
414
417
  'chatbotOpened',
415
418
  'chatbotClosed',
416
419
  'singleThreadDelete',
@@ -625,16 +628,16 @@ const setProductAction = (destination, sessionId, productId, action, value) => {
625
628
  const updatedLocal = { [sessionId]: local[sessionId] };
626
629
  saveLocalStorageData(destination, updatedLocal);
627
630
  };
628
- const getShopGPTLoaded = (destination, sessionId) => {
631
+ const getWasUserExposed = (destination, sessionId) => {
629
632
  var _a, _b;
630
633
  const local = getLocalStorageData(destination);
631
634
  if (!local || !sessionId) {
632
635
  logger.error('No local storage data or session id');
633
636
  return false;
634
637
  }
635
- return (_b = (_a = local[sessionId]) === null || _a === void 0 ? void 0 : _a.isShopGPTLoaded) !== null && _b !== void 0 ? _b : false;
638
+ return (_b = (_a = local[sessionId]) === null || _a === void 0 ? void 0 : _a.exposed) !== null && _b !== void 0 ? _b : false;
636
639
  };
637
- const setShopGPTLoaded = (destination, sessionId, value) => {
640
+ const setWasUserExposed = (destination, sessionId, value) => {
638
641
  const local = getLocalStorageData(destination);
639
642
  if (!local || !sessionId) {
640
643
  logger.error('No local storage data or session id');
@@ -642,14 +645,60 @@ const setShopGPTLoaded = (destination, sessionId, value) => {
642
645
  }
643
646
  local[sessionId] = {
644
647
  ...local[sessionId],
645
- isShopGPTLoaded: value,
648
+ exposed: value,
646
649
  };
647
650
  // Clear other sessions
648
651
  const updatedLocal = { [sessionId]: local[sessionId] };
649
652
  saveLocalStorageData(destination, updatedLocal);
650
653
  };
654
+ const setUserType = (destination, sessionId, value) => {
655
+ const local = getLocalStorageData(destination);
656
+ if (!local || !sessionId) {
657
+ logger.error('No session id');
658
+ return;
659
+ }
660
+ local[sessionId] = {
661
+ ...local[sessionId],
662
+ userType: value,
663
+ };
664
+ // Clear other sessions
665
+ const updatedLocal = { [sessionId]: local[sessionId] };
666
+ saveLocalStorageData(destination, updatedLocal);
667
+ };
668
+ const getUserType = (destination, sessionId) => {
669
+ var _a;
670
+ const local = getLocalStorageData(destination);
671
+ if (!sessionId) {
672
+ logger.error('No session id');
673
+ return;
674
+ }
675
+ return (_a = local === null || local === void 0 ? void 0 : local[sessionId]) === null || _a === void 0 ? void 0 : _a.userType;
676
+ };
677
+ const setIsBotOpened = (destination, sessionId, value) => {
678
+ const local = getLocalStorageData(destination);
679
+ if (!local || !sessionId) {
680
+ logger.error('No session id');
681
+ return;
682
+ }
683
+ local[sessionId] = {
684
+ ...local[sessionId],
685
+ opened: value,
686
+ };
687
+ // Clear other sessions
688
+ const updatedLocal = { [sessionId]: local[sessionId] };
689
+ saveLocalStorageData(destination, updatedLocal);
690
+ };
691
+ const getIsBotOpened = (destination, sessionId) => {
692
+ var _a;
693
+ const local = getLocalStorageData(destination);
694
+ if (!sessionId) {
695
+ logger.error('No session id');
696
+ return;
697
+ }
698
+ return (_a = local === null || local === void 0 ? void 0 : local[sessionId]) === null || _a === void 0 ? void 0 : _a.opened;
699
+ };
651
700
 
652
- const createShopGPTAPI = ({ fetch: fetchImpl = window.fetch, baseURL, userId, storeAPI, sessionId, }) => {
701
+ const createShopGPTAPI = ({ fetch: fetchImpl = window.fetch, baseURL, userId, storeAPI, sessionId, sendTag, }) => {
653
702
  if (!baseURL) {
654
703
  throw new Error(`baseURL missing`);
655
704
  }
@@ -779,9 +828,12 @@ const createShopGPTAPI = ({ fetch: fetchImpl = window.fetch, baseURL, userId, st
779
828
  const data = (await response.json());
780
829
  return data.customPrompts;
781
830
  };
782
- const sendEvent = (action, currency, actionData) => {
831
+ const sendEvent = (action, currency, actionData, clickData) => {
783
832
  var _a;
784
833
  const storageData = (_a = getProductActions(baseURL, sessionId)) !== null && _a !== void 0 ? _a : {};
834
+ const userType = getUserType(baseURL, sessionId);
835
+ const exposed = getWasUserExposed(baseURL, sessionId);
836
+ const opened = getIsBotOpened(baseURL, sessionId);
785
837
  // This endpoint sends user events to the server, we don't need to wait for the response
786
838
  fetchImpl(getURL('/user/event'), {
787
839
  method: 'POST',
@@ -793,7 +845,9 @@ const createShopGPTAPI = ({ fetch: fetchImpl = window.fetch, baseURL, userId, st
793
845
  storageData: {
794
846
  session: storageData,
795
847
  preview: hasPreviewKey(),
796
- isShopGPTLoaded: true, // The fact that sendEvent was called means that the ShopGPT is loaded
848
+ userType: userType,
849
+ exposed,
850
+ opened: !!opened,
797
851
  },
798
852
  }),
799
853
  credentials: 'include',
@@ -804,6 +858,21 @@ const createShopGPTAPI = ({ fetch: fetchImpl = window.fetch, baseURL, userId, st
804
858
  }
805
859
  })
806
860
  .catch(logger.error);
861
+ sendTag({
862
+ eventId: crypto.randomUUID(),
863
+ eventName: action,
864
+ data: {
865
+ ...actionData,
866
+ ...clickData,
867
+ userType,
868
+ exposed,
869
+ storageData,
870
+ opened: !!opened,
871
+ },
872
+ providers: {
873
+ shopGPT: true,
874
+ },
875
+ });
807
876
  };
808
877
  return {
809
878
  processQuery,
@@ -821,7 +890,7 @@ const createShopGPTAPI = ({ fetch: fetchImpl = window.fetch, baseURL, userId, st
821
890
  // eslint-disable-next-line @nx/enforce-module-boundaries
822
891
  const error = (message) => console.error(message);
823
892
  const init = (params) => {
824
- var _a, _b, _c, _d, _e, _f;
893
+ var _a, _b, _c;
825
894
  if (typeof window == 'undefined' || typeof document == 'undefined') {
826
895
  // if loaded in non-browser SDKs, return early
827
896
  return;
@@ -840,7 +909,6 @@ const init = (params) => {
840
909
  return;
841
910
  }
842
911
  const { enabled, mode, devMode, merchantUrl, profiles, productHandles, targetPath, view, brandName, quickPrompts, merchantImage, latestThreadLoad, botIconUrl, css, nudge, loadUIManually, } = (_c = params.manifest.variables) !== null && _c !== void 0 ? _c : {};
843
- setShopGPTLoaded(params.baseUrl, (_d = params.session) === null || _d === void 0 ? void 0 : _d.sessionId, !loadUIManually);
844
912
  const experiment = createExperiment({
845
913
  name: getExperimentName(mode),
846
914
  userId: params.userId,
@@ -850,42 +918,65 @@ const init = (params) => {
850
918
  if (experiment.name === 'preview' && shouldShowUI) {
851
919
  logger.log('Enabling UI in preview mode');
852
920
  }
853
- if (shouldShowUI) {
854
- const uiImplementation = window[registryKey].ui;
855
- if (!uiImplementation) {
856
- error('UI implementation is missing');
857
- return;
921
+ // once we implement a general version with togglable option to discriminate
922
+ // between anon/known, we'll be able to skip creating this promise before
923
+ // init and possibly loading the UI
924
+ new Promise((resolve) => {
925
+ var _a;
926
+ const userType = getUserType(params.baseUrl, (_a = params.session) === null || _a === void 0 ? void 0 : _a.sessionId);
927
+ if (userType) {
928
+ return resolve();
858
929
  }
930
+ params.getEdgeData(['email'], (data) => {
931
+ var _a;
932
+ setUserType(params.baseUrl, (_a = params.session) === null || _a === void 0 ? void 0 : _a.sessionId, data['emailExists'] ? 'known' : 'anon');
933
+ resolve();
934
+ });
935
+ }).then(() => {
936
+ var _a, _b;
859
937
  const shopGPTAPI = createShopGPTAPI({
860
938
  baseURL: params.baseUrl,
861
939
  storeAPI,
862
940
  userId: params.userId,
863
- sessionId: (_e = params.session) === null || _e === void 0 ? void 0 : _e.sessionId,
941
+ sessionId: (_a = params.session) === null || _a === void 0 ? void 0 : _a.sessionId,
942
+ sendTag: params.sendTag,
864
943
  });
865
- uiImplementation.init({
866
- destination: params.baseUrl,
867
- storeAPI,
868
- shopGPTAPI,
869
- devMode,
870
- view,
871
- merchantUrl,
872
- profiles,
873
- productHandles,
874
- path: targetPath,
875
- brandName,
876
- quickPrompts,
877
- merchantImage,
878
- latestThreadLoad: latestThreadLoad !== null && latestThreadLoad !== void 0 ? latestThreadLoad : DEFAULT_MAX_THREAD_AGE,
879
- botIconUrl,
880
- css,
881
- nudge,
882
- sessionId: (_f = params.session) === null || _f === void 0 ? void 0 : _f.sessionId,
883
- loadUIManually,
944
+ shopGPTAPI.sendEvent('shopGPTInitialized', undefined, undefined, {
945
+ groupName: experiment.groupName,
884
946
  });
885
- if (!loadUIManually) {
886
- uiImplementation.loadUI();
947
+ if (shouldShowUI) {
948
+ const uiImplementation = window[registryKey].ui;
949
+ if (!uiImplementation) {
950
+ error('UI implementation is missing');
951
+ return;
952
+ }
953
+ uiImplementation.init({
954
+ destination: params.baseUrl,
955
+ storeAPI,
956
+ shopGPTAPI,
957
+ devMode,
958
+ view,
959
+ merchantUrl,
960
+ profiles,
961
+ productHandles,
962
+ path: targetPath,
963
+ brandName,
964
+ quickPrompts,
965
+ merchantImage,
966
+ latestThreadLoad: latestThreadLoad !== null && latestThreadLoad !== void 0 ? latestThreadLoad : DEFAULT_MAX_THREAD_AGE,
967
+ botIconUrl,
968
+ css,
969
+ nudge,
970
+ sessionId: (_b = params.session) === null || _b === void 0 ? void 0 : _b.sessionId,
971
+ loadUIManually,
972
+ });
973
+ const searchParams = new URLSearchParams(window.location.search);
974
+ const hasSource = searchParams.get('utm_source') === 'shopgpt';
975
+ if (!loadUIManually || hasSource) {
976
+ uiImplementation.loadUI();
977
+ }
887
978
  }
888
- }
979
+ });
889
980
  };
890
981
 
891
982
  const getClickedProductsInContents = (destination, sessionId, data) => {
@@ -897,7 +988,7 @@ const getClickedProductsInContents = (destination, sessionId, data) => {
897
988
  return contents.flatMap((content) => { var _a; return ((_a = storedData[content.id]) === null || _a === void 0 ? void 0 : _a.clicked) ? [content.id] : []; });
898
989
  };
899
990
  const tag = ({ eventName, destination, data, sessionId, }) => {
900
- var _a;
991
+ var _a, _b;
901
992
  const clickedProducts = getClickedProductsInContents(destination, sessionId, data);
902
993
  if (eventName === 'AddToCart') {
903
994
  clickedProducts === null || clickedProducts === void 0 ? void 0 : clickedProducts.forEach((id) => {
@@ -912,7 +1003,9 @@ const tag = ({ eventName, destination, data, sessionId, }) => {
912
1003
  return {
913
1004
  session: getProductActions(destination, sessionId),
914
1005
  preview: hasPreviewKey(),
915
- isShopGPTLoaded: (_a = getShopGPTLoaded(destination, sessionId)) !== null && _a !== void 0 ? _a : false,
1006
+ exposed: (_a = getWasUserExposed(destination, sessionId)) !== null && _a !== void 0 ? _a : false,
1007
+ userType: getUserType(destination, sessionId),
1008
+ opened: (_b = getIsBotOpened(destination, sessionId)) !== null && _b !== void 0 ? _b : false,
916
1009
  };
917
1010
  };
918
1011
 
@@ -1782,13 +1875,13 @@ const productItemStyles = i$4 `
1782
1875
  .product {
1783
1876
  display: flex;
1784
1877
  gap: 16px;
1878
+ cursor: pointer;
1785
1879
 
1786
1880
  img {
1787
1881
  width: 150px;
1788
1882
  height: 186px;
1789
1883
  object-position: center;
1790
1884
  object-fit: contain;
1791
- cursor: pointer;
1792
1885
  }
1793
1886
  }
1794
1887
 
@@ -1813,7 +1906,6 @@ const productItemStyles = i$4 `
1813
1906
  text-overflow: ellipsis;
1814
1907
  word-break: break-word;
1815
1908
  white-space: normal;
1816
- cursor: pointer;
1817
1909
  }
1818
1910
 
1819
1911
  .product-variation-details {
@@ -1924,11 +2016,14 @@ class ProductItem extends r$2 {
1924
2016
  ${this.getLocalPrice(comparedAtPrice)}
1925
2017
  </p>`;
1926
2018
  }
1927
- redirect(url) {
2019
+ openProduct(url) {
1928
2020
  if (!url) {
1929
2021
  return;
1930
2022
  }
1931
- open(url, '_self');
2023
+ const link = new URL(url);
2024
+ link.searchParams.set('utm_source', 'shopgpt');
2025
+ link.searchParams.set('utm_medium', 'chat');
2026
+ open(link, '_self');
1932
2027
  }
1933
2028
  renderVariantTitles() {
1934
2029
  if (this.product.hasOnlyDefaultVariant) {
@@ -1938,39 +2033,32 @@ class ProductItem extends r$2 {
1938
2033
  <p class="product-variation-details">${option.name}: ${option.value}</p>
1939
2034
  `);
1940
2035
  }
1941
- productClicked(productId, price, url) {
1942
- if (productId) {
2036
+ productClicked(product) {
2037
+ if (product.id) {
2038
+ const price = product.variants[0].price;
1943
2039
  this.dispatchEvent(new CustomEvent('product-clicked', {
1944
2040
  detail: {
1945
- productId,
2041
+ id: product.id,
1946
2042
  value: price ? parseFloat(price) : undefined,
2043
+ variantId: product.variants[0].id,
2044
+ title: product.title,
2045
+ url: product.url,
2046
+ query: this.query,
2047
+ response: this.response,
2048
+ rank: this.rank,
1947
2049
  },
1948
2050
  composed: true,
1949
2051
  bubbles: true,
1950
2052
  }));
1951
2053
  }
1952
- this.redirect(url);
2054
+ this.openProduct(product.url);
1953
2055
  }
1954
2056
  render() {
1955
2057
  return x `
1956
- <div class="product">
1957
- <img
1958
- src=${this.product.image.url}
1959
- alt=${this.product.image.alt}
1960
- @click=${() => {
1961
- var _a;
1962
- return this.productClicked(this.product.id, this.product.variants[0].price, (_a = this.product) === null || _a === void 0 ? void 0 : _a.url);
1963
- }}
1964
- />
2058
+ <div class="product" @click=${() => this.productClicked(this.product)}>
2059
+ <img src=${this.product.image.url} alt=${this.product.image.alt} />
1965
2060
  <div class="content">
1966
- <p
1967
- class="product-name"
1968
- title=${this.product.title}
1969
- @click=${() => {
1970
- var _a;
1971
- return this.productClicked(this.product.id, this.product.variants[0].price, (_a = this.product) === null || _a === void 0 ? void 0 : _a.url);
1972
- }}
1973
- >
2061
+ <p class="product-name" title=${this.product.title}>
1974
2062
  ${this.product.title}
1975
2063
  </p>
1976
2064
  ${this.renderVariantTitles()}
@@ -1978,15 +2066,7 @@ class ProductItem extends r$2 {
1978
2066
  ${this.getComparedAtPrice(this.product.variants[0].comparedAtPrice, this.product.variants[0].price)}
1979
2067
  <p>${this.getLocalPrice(this.product.variants[0].price)}</p>
1980
2068
  </div>
1981
- <button
1982
- class="btn-view-product"
1983
- @click=${() => {
1984
- var _a;
1985
- return this.productClicked(this.product.id, this.product.variants[0].price, (_a = this.product) === null || _a === void 0 ? void 0 : _a.url);
1986
- }}
1987
- >
1988
- View Product
1989
- </button>
2069
+ <button class="btn-view-product">View Product</button>
1990
2070
  </div>
1991
2071
  </div>
1992
2072
  `;
@@ -2001,6 +2081,18 @@ __decorate([
2001
2081
  n({ type: Object }),
2002
2082
  __metadata("design:type", Object)
2003
2083
  ], ProductItem.prototype, "siteCurrency", void 0);
2084
+ __decorate([
2085
+ n({ type: String }),
2086
+ __metadata("design:type", Object)
2087
+ ], ProductItem.prototype, "query", void 0);
2088
+ __decorate([
2089
+ n({ type: String }),
2090
+ __metadata("design:type", String)
2091
+ ], ProductItem.prototype, "response", void 0);
2092
+ __decorate([
2093
+ n({ type: Number }),
2094
+ __metadata("design:type", Number)
2095
+ ], ProductItem.prototype, "rank", void 0);
2004
2096
  if (!customElements.get('product-item')) {
2005
2097
  customElements.define('product-item', ProductItem);
2006
2098
  }
@@ -2117,7 +2209,7 @@ class ProductsList extends r$2 {
2117
2209
  return x `
2118
2210
  <div class="products-wrapper">
2119
2211
  <div class="products" @scroll=${this.updateButtonsState}>
2120
- ${o$1(this.products, (product) => x `
2212
+ ${o$1(this.products, (product, index) => x `
2121
2213
  <div
2122
2214
  class=${e$1({
2123
2215
  'product-container': true,
@@ -2125,8 +2217,11 @@ class ProductsList extends r$2 {
2125
2217
  })}
2126
2218
  >
2127
2219
  <product-item
2220
+ .query=${this.query}
2221
+ .response=${this.response}
2128
2222
  .product=${product}
2129
2223
  .siteCurrency=${this.siteCurrency}
2224
+ .rank=${index + 1}
2130
2225
  ></product-item>
2131
2226
  </div>
2132
2227
  `)}
@@ -2154,6 +2249,14 @@ __decorate([
2154
2249
  n({ type: Object }),
2155
2250
  __metadata("design:type", Object)
2156
2251
  ], ProductsList.prototype, "siteCurrency", void 0);
2252
+ __decorate([
2253
+ n({ type: String }),
2254
+ __metadata("design:type", Object)
2255
+ ], ProductsList.prototype, "query", void 0);
2256
+ __decorate([
2257
+ n({ type: String }),
2258
+ __metadata("design:type", String)
2259
+ ], ProductsList.prototype, "response", void 0);
2157
2260
  __decorate([
2158
2261
  r(),
2159
2262
  __metadata("design:type", Object)
@@ -2200,6 +2303,7 @@ class ProductsSection extends r$2 {
2200
2303
  `;
2201
2304
  }
2202
2305
  render() {
2306
+ var _a;
2203
2307
  if (this.isLoadingHistory || this.isLoadingThreads) {
2204
2308
  return x ` <load-spinner></load-spinner> `;
2205
2309
  }
@@ -2210,18 +2314,25 @@ class ProductsSection extends r$2 {
2210
2314
  }
2211
2315
  const topResult = this.products[0];
2212
2316
  const others = this.products.slice(1);
2317
+ const query = (_a = this.messages) === null || _a === void 0 ? void 0 : _a[1];
2318
+ const response = this.messages[0];
2213
2319
  return x `
2214
2320
  <div class="top-result">
2215
2321
  <h2>Top Result</h2>
2216
2322
  <product-item
2323
+ .query=${query === null || query === void 0 ? void 0 : query.message}
2324
+ .response=${response === null || response === void 0 ? void 0 : response.message}
2217
2325
  .product=${topResult}
2218
2326
  .siteCurrency=${this.siteCurrency}
2327
+ .rank=${1}
2219
2328
  ></product-item>
2220
2329
  </div>
2221
2330
  <span class="line"></span>
2222
2331
  <div class="others">
2223
2332
  <h2>Other Recommendations</h2>
2224
2333
  <products-list
2334
+ .query=${query === null || query === void 0 ? void 0 : query.message}
2335
+ .response=${response === null || response === void 0 ? void 0 : response.message}
2225
2336
  .products=${others}
2226
2337
  .siteCurrency=${this.siteCurrency}
2227
2338
  .viewType=${'overlay'}
@@ -2267,6 +2378,10 @@ __decorate([
2267
2378
  n({ type: String }),
2268
2379
  __metadata("design:type", String)
2269
2380
  ], ProductsSection.prototype, "css", void 0);
2381
+ __decorate([
2382
+ n({ type: Array }),
2383
+ __metadata("design:type", Array)
2384
+ ], ProductsSection.prototype, "messages", void 0);
2270
2385
  if (!customElements.get('products-section')) {
2271
2386
  customElements.define('products-section', ProductsSection);
2272
2387
  }
@@ -3993,9 +4108,9 @@ class ChatSection extends r$2 {
3993
4108
  }
3994
4109
  await this.sendMessageToServer(e, message, isPrompt);
3995
4110
  }
3996
- sendEvent(action, actionData) {
4111
+ sendEvent(action, actionData, clickData) {
3997
4112
  this.dispatchEvent(new CustomEvent('send-event', {
3998
- detail: { action, actionData },
4113
+ detail: { action, actionData, clickData },
3999
4114
  composed: true,
4000
4115
  bubbles: true,
4001
4116
  }));
@@ -4026,24 +4141,38 @@ class ChatSection extends r$2 {
4026
4141
  }));
4027
4142
  this.deleteThreadId = '';
4028
4143
  }
4029
- handleFeedback(rating, messageId, queryMessageId, comment) {
4030
- var _a, _b;
4144
+ handleFeedback(rating, messageId, queryMessageId, comment, query, response) {
4145
+ var _a, _b, _c, _d;
4031
4146
  if (rating === 'bad') {
4032
- this.sendEvent('thumbsDown');
4147
+ this.sendEvent('thumbsDown', undefined, {
4148
+ messageId,
4149
+ threadId: ((_a = this.thread) === null || _a === void 0 ? void 0 : _a.threadId) || '',
4150
+ rating,
4151
+ comment: comment !== null && comment !== void 0 ? comment : '',
4152
+ query: query !== null && query !== void 0 ? query : '',
4153
+ response: response !== null && response !== void 0 ? response : '',
4154
+ });
4033
4155
  this.feedbackDetails = {
4034
4156
  messageId,
4035
4157
  queryMessageId,
4036
- threadId: ((_a = this.thread) === null || _a === void 0 ? void 0 : _a.threadId) || '',
4158
+ threadId: ((_b = this.thread) === null || _b === void 0 ? void 0 : _b.threadId) || '',
4037
4159
  comment,
4038
4160
  };
4039
4161
  return;
4040
4162
  }
4041
- this.sendEvent('thumbsUp');
4163
+ this.sendEvent('thumbsUp', undefined, {
4164
+ messageId,
4165
+ threadId: ((_c = this.thread) === null || _c === void 0 ? void 0 : _c.threadId) || '',
4166
+ rating,
4167
+ comment: comment !== null && comment !== void 0 ? comment : '',
4168
+ query: query !== null && query !== void 0 ? query : '',
4169
+ response: response !== null && response !== void 0 ? response : '',
4170
+ });
4042
4171
  this.dispatchEvent(new CustomEvent('submit-feedback', {
4043
4172
  detail: {
4044
4173
  messageId: messageId,
4045
4174
  queryMessageId: queryMessageId,
4046
- threadId: (_b = this.thread) === null || _b === void 0 ? void 0 : _b.threadId,
4175
+ threadId: (_d = this.thread) === null || _d === void 0 ? void 0 : _d.threadId,
4047
4176
  feedback: {
4048
4177
  rating,
4049
4178
  comment: null,
@@ -4078,8 +4207,11 @@ class ChatSection extends r$2 {
4078
4207
  <span class="line"></span>
4079
4208
  <div class="product-container">
4080
4209
  <product-item
4210
+ .query=${queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.message}
4211
+ .response=${message.message}
4081
4212
  .product=${message.products[0]}
4082
4213
  .siteCurrency=${this.siteCurrency}
4214
+ .rank=${1}
4083
4215
  ></product-item>
4084
4216
  </div>
4085
4217
  `
@@ -4088,16 +4220,18 @@ class ChatSection extends r$2 {
4088
4220
  </div>
4089
4221
  ${this.viewType === 'modal' && message.products
4090
4222
  ? x ` <products-list
4223
+ .query=${queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.message}
4224
+ .response=${message.message}
4091
4225
  .products=${message.products}
4092
4226
  .siteCurrency=${this.siteCurrency}
4093
4227
  .viewType=${this.viewType}
4094
4228
  ></products-list>`
4095
4229
  : E}
4096
4230
  ${message.messageId && (queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.messageId)
4097
- ? x `<div class="bot-response-actions">
4231
+ ? x ` <div class="bot-response-actions">
4098
4232
  <button
4099
4233
  type="button"
4100
- @click=${this.handleFeedback.bind(this, 'good', message.messageId, queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.messageId, (_b = message.feedback) === null || _b === void 0 ? void 0 : _b.comment)}
4234
+ @click=${this.handleFeedback.bind(this, 'good', message.messageId, queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.messageId, (_b = message.feedback) === null || _b === void 0 ? void 0 : _b.comment, queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.message, message === null || message === void 0 ? void 0 : message.message)}
4101
4235
  >
4102
4236
  ${((_c = message.feedback) === null || _c === void 0 ? void 0 : _c.rating) === 'good'
4103
4237
  ? thumbsUpFilledBtn
@@ -4105,7 +4239,7 @@ class ChatSection extends r$2 {
4105
4239
  </button>
4106
4240
  <button
4107
4241
  type="button"
4108
- @click=${this.handleFeedback.bind(this, 'bad', message.messageId, queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.messageId, (_d = message.feedback) === null || _d === void 0 ? void 0 : _d.comment)}
4242
+ @click=${this.handleFeedback.bind(this, 'bad', message.messageId, queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.messageId, (_d = message.feedback) === null || _d === void 0 ? void 0 : _d.comment, queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.message, message === null || message === void 0 ? void 0 : message.message)}
4109
4243
  >
4110
4244
  ${((_e = message.feedback) === null || _e === void 0 ? void 0 : _e.rating) === 'bad'
4111
4245
  ? thumbsDownFilledBtn
@@ -4118,7 +4252,7 @@ class ChatSection extends r$2 {
4118
4252
  }
4119
4253
  renderBotIcon() {
4120
4254
  if (this.botIconUrl) {
4121
- return x `<div class="bot-icon">
4255
+ return x ` <div class="bot-icon">
4122
4256
  <img src=${this.botIconUrl} width="30" height="30" />
4123
4257
  </div>`;
4124
4258
  }
@@ -4126,7 +4260,7 @@ class ChatSection extends r$2 {
4126
4260
  }
4127
4261
  chatWindow() {
4128
4262
  if (this.isLoadingHistory || this.isLoadingThreads) {
4129
- return x `<div class="messages loading">
4263
+ return x ` <div class="messages loading">
4130
4264
  <load-spinner></load-spinner>
4131
4265
  </div>`;
4132
4266
  }
@@ -4139,7 +4273,7 @@ class ChatSection extends r$2 {
4139
4273
  </div>`
4140
4274
  : ''}
4141
4275
  ${this.isFailed
4142
- ? x `<div class="message bot">
4276
+ ? x ` <div class="message bot">
4143
4277
  <div>${this.renderBotIcon()}</div>
4144
4278
  <div>
4145
4279
  <p>
@@ -4159,18 +4293,20 @@ class ChatSection extends r$2 {
4159
4293
  })}
4160
4294
  ${!this.fromAd || !this.thread
4161
4295
  ? x `
4162
- <div class="message bot">
4163
- <div>${this.renderBotIcon()}</div>
4164
- <div>
4165
- <p>
4166
- Hi,
4167
- ${this.brandName ? x `Welcome to ${this.brandName}.` : E}
4168
- I'm here to help you find the perfect product. Pick a suggested
4169
- prompt from below, or enter your own query.
4170
- </p>
4171
- </div>
4172
- </div>
4173
- </div>`
4296
+ <div class="message bot">
4297
+ <div>${this.renderBotIcon()}</div>
4298
+ <div>
4299
+ <p>
4300
+ Hi,
4301
+ ${this.brandName
4302
+ ? x `Welcome to ${this.brandName}.`
4303
+ : E}
4304
+ I'm here to help you find the perfect product. Pick a suggested
4305
+ prompt from below, or enter your own query.
4306
+ </p>
4307
+ </div>
4308
+ </div>
4309
+ </div>`
4174
4310
  : E}
4175
4311
  </div>
4176
4312
  `;
@@ -4197,7 +4333,9 @@ class ChatSection extends r$2 {
4197
4333
  class="prompt"
4198
4334
  @click=${(e) => {
4199
4335
  this.processMessage(e, prompt, true);
4200
- this.sendEvent('promptClicked');
4336
+ this.sendEvent('promptClicked', undefined, {
4337
+ promptName: prompt,
4338
+ });
4201
4339
  }}
4202
4340
  >
4203
4341
  ${prompt}
@@ -4211,7 +4349,9 @@ class ChatSection extends r$2 {
4211
4349
  href=${link}
4212
4350
  target="_blank"
4213
4351
  rel="noopener"
4214
- @click=${() => this.sendEvent('promptClicked')}
4352
+ @click=${() => this.sendEvent('promptClicked', undefined, {
4353
+ promptName: prompt,
4354
+ })}
4215
4355
  >
4216
4356
  ${prompt}
4217
4357
  </a>
@@ -4402,7 +4542,7 @@ class ChatSection extends r$2 {
4402
4542
  <div class="title-wrapper">
4403
4543
  <h2>Search History</h2>
4404
4544
  ${this.chatThreads.size
4405
- ? x `<div
4545
+ ? x ` <div
4406
4546
  class="trash-icon"
4407
4547
  @click=${() => {
4408
4548
  if (this.isStreaming) {
@@ -4808,9 +4948,6 @@ class ShopGPT extends r$2 {
4808
4948
  this.startNudgeTimer();
4809
4949
  }
4810
4950
  disconnectedCallback() {
4811
- if (!this.loadUIManually) {
4812
- window.removeEventListener('edgetag-initialized', this.loadData);
4813
- }
4814
4951
  window.removeEventListener('popstate', this.onPopState);
4815
4952
  if (this.nudgeTimer) {
4816
4953
  window.clearTimeout(this.nudgeTimer);
@@ -4818,16 +4955,9 @@ class ShopGPT extends r$2 {
4818
4955
  super.disconnectedCallback();
4819
4956
  }
4820
4957
  init() {
4821
- if (this.loadUIManually) {
4822
- // this is because edgetag-initialized will already be
4823
- // triggered before the loadUI function is called to load the UI
4824
- this.loadData();
4825
- }
4826
- else {
4827
- window.addEventListener('edgetag-initialized', this.loadData);
4828
- }
4958
+ this.loadData();
4829
4959
  window.addEventListener('popstate', this.onPopState);
4830
- this.shopGPTAPI.sendEvent('shopGPTInitialized', this.getSiteCurrency().currency);
4960
+ this.shopGPTAPI.sendEvent('shopGPTLoaded');
4831
4961
  if (!this.view || this.view === 'overlay') {
4832
4962
  delay(DIALOG_DELAY)
4833
4963
  .then(() => {
@@ -4843,6 +4973,14 @@ class ShopGPT extends r$2 {
4843
4973
  })
4844
4974
  .catch(logger.error);
4845
4975
  }
4976
+ else if (this.view === 'modal') {
4977
+ const searchParams = new URLSearchParams(window.location.search);
4978
+ const hasSource = searchParams.get('utm_source') === 'shopgpt';
4979
+ // If the url has `utm_source` open the popup when reloaded
4980
+ if (hasSource) {
4981
+ this.modalState = 'open';
4982
+ }
4983
+ }
4846
4984
  }
4847
4985
  setChatTitle(threadId, title) {
4848
4986
  if (!title || !threadId) {
@@ -4971,10 +5109,17 @@ class ShopGPT extends r$2 {
4971
5109
  }
4972
5110
  }
4973
5111
  async setSelectedThreadId(threadId, silent) {
5112
+ var _a, _b, _c, _d;
4974
5113
  this.isFailed = false;
5114
+ const currentThreadId = this.selectedThreadId;
4975
5115
  this.selectedThreadId = threadId;
4976
5116
  if (threadId && !silent) {
4977
- this.shopGPTAPI.sendEvent('switchThread');
5117
+ this.shopGPTAPI.sendEvent('switchThread', undefined, undefined, {
5118
+ previousThread: currentThreadId,
5119
+ activeThread: threadId,
5120
+ previousThreadTitle: (_b = (_a = this.chatThreads.get(currentThreadId)) === null || _a === void 0 ? void 0 : _a.title) !== null && _b !== void 0 ? _b : '',
5121
+ activeThreadTitle: (_d = (_c = this.chatThreads.get(this.selectedThreadId)) === null || _c === void 0 ? void 0 : _c.title) !== null && _d !== void 0 ? _d : '',
5122
+ });
4978
5123
  }
4979
5124
  await Promise.all([
4980
5125
  this.loadHistory(threadId),
@@ -5000,6 +5145,7 @@ class ShopGPT extends r$2 {
5000
5145
  }
5001
5146
  }
5002
5147
  handleThreadDelete(e) {
5148
+ var _a, _b;
5003
5149
  e.stopPropagation();
5004
5150
  this.isLoadingThreads = true;
5005
5151
  const threadId = e.detail.threadId;
@@ -5007,7 +5153,10 @@ class ShopGPT extends r$2 {
5007
5153
  logger.error('ThreadId is missing to delete the thread!');
5008
5154
  return;
5009
5155
  }
5010
- this.shopGPTAPI.sendEvent('singleThreadDelete');
5156
+ this.shopGPTAPI.sendEvent('singleThreadDelete', undefined, undefined, {
5157
+ thread: threadId,
5158
+ threadTitle: (_b = (_a = this.chatThreads.get(threadId)) === null || _a === void 0 ? void 0 : _a.title) !== null && _b !== void 0 ? _b : '',
5159
+ });
5011
5160
  this.shopGPTAPI
5012
5161
  .deleteSingleThread(threadId)
5013
5162
  .then(this.loadChatThreads.bind(this))
@@ -5135,7 +5284,10 @@ class ShopGPT extends r$2 {
5135
5284
  try {
5136
5285
  this.isPreviousMessagePrompt = isPrompt;
5137
5286
  if (!isPrompt) {
5138
- this.shopGPTAPI.sendEvent('queryInteractions', this.getSiteCurrency().currency);
5287
+ this.shopGPTAPI.sendEvent('queryInteractions', this.getSiteCurrency().currency, undefined, {
5288
+ query: message,
5289
+ threadId: this.selectedThreadId,
5290
+ });
5139
5291
  }
5140
5292
  this.messages = [{ sender: 'user', message }, ...this.messages];
5141
5293
  this.isTyping = true;
@@ -5167,15 +5319,25 @@ class ShopGPT extends r$2 {
5167
5319
  }
5168
5320
  sendEvent(e) {
5169
5321
  e.stopPropagation();
5170
- this.shopGPTAPI.sendEvent(e.detail.action, this.getSiteCurrency().currency, e.detail.actionData);
5322
+ this.shopGPTAPI.sendEvent(e.detail.action, this.getSiteCurrency().currency, e.detail.actionData, e.detail.clickData);
5171
5323
  }
5172
5324
  productClicked(e) {
5325
+ var _a, _b;
5173
5326
  e.stopPropagation();
5174
- setProductAction(this.destination, this.sessionId, e.detail.productId, 'clicked', true);
5327
+ setProductAction(this.destination, this.sessionId, e.detail.id, 'clicked', true);
5175
5328
  this.shopGPTAPI.sendEvent('productRecommendationClicked', this.getSiteCurrency().currency, {
5176
- productId: e.detail.productId,
5329
+ productId: e.detail.id,
5177
5330
  value: e.detail.value,
5178
5331
  isPrompt: this.isPreviousMessagePrompt,
5332
+ }, {
5333
+ threadId: this.selectedThreadId,
5334
+ query: (_a = e.detail.query) !== null && _a !== void 0 ? _a : '',
5335
+ response: (_b = e.detail.response) !== null && _b !== void 0 ? _b : '',
5336
+ currency: this.getSiteCurrency().currency,
5337
+ variantId: e.detail.variantId,
5338
+ url: e.detail.url,
5339
+ title: e.detail.title,
5340
+ rank: e.detail.rank,
5179
5341
  });
5180
5342
  }
5181
5343
  getSiteCurrency() {
@@ -5206,6 +5368,7 @@ class ShopGPT extends r$2 {
5206
5368
  .css=${this.css}
5207
5369
  ></chat-threads>
5208
5370
  <products-section
5371
+ .messages=${this.messages}
5209
5372
  .merchantImage=${this.merchantImage}
5210
5373
  .products=${this.products}
5211
5374
  .isLoadingHistory=${this.isLoadingHistory}
@@ -5251,26 +5414,23 @@ class ShopGPT extends r$2 {
5251
5414
  <button
5252
5415
  @click=${(e) => {
5253
5416
  e.preventDefault();
5254
- this.shopGPTAPI.sendEvent('chatbotOpened', this.getSiteCurrency().currency);
5255
- this.modalState = 'open';
5256
- this.handleUserInteraction();
5417
+ this.openModal();
5257
5418
  }}
5258
5419
  >
5259
5420
  ${chatIcon}
5260
5421
  </button>
5261
5422
  ${((_a = this.nudge) === null || _a === void 0 ? void 0 : _a.show) && this.showNudge
5262
- ? x `<div
5423
+ ? x ` <div
5263
5424
  class="nudge"
5264
5425
  @click=${(e) => {
5265
5426
  e.preventDefault();
5266
- this.modalState = 'open';
5267
- this.handleUserInteraction();
5427
+ this.openModal();
5268
5428
  }}
5269
5429
  >
5270
5430
  Hi there! I'm an AI Agent to help you find the perfect product.
5271
5431
  What are you looking for today?
5272
5432
  </div>`
5273
- : x `<div class="chatbot-hover-text">
5433
+ : x ` <div class="chatbot-hover-text">
5274
5434
  What are you looking for today?
5275
5435
  </div>`}
5276
5436
  </div>`;
@@ -5314,6 +5474,12 @@ class ShopGPT extends r$2 {
5314
5474
  </div>
5315
5475
  `;
5316
5476
  }
5477
+ openModal() {
5478
+ setIsBotOpened(this.destination, this.sessionId, true);
5479
+ this.shopGPTAPI.sendEvent('chatbotOpened');
5480
+ this.modalState = 'open';
5481
+ this.handleUserInteraction();
5482
+ }
5317
5483
  startNudgeTimer() {
5318
5484
  var _a, _b;
5319
5485
  if (this.view !== 'modal' || !((_a = this.nudge) === null || _a === void 0 ? void 0 : _a.show)) {
@@ -5461,14 +5627,13 @@ if (typeof window != 'undefined' && typeof document != 'undefined') {
5461
5627
  logger.log('ShopGPT component added already!');
5462
5628
  return;
5463
5629
  }
5630
+ setWasUserExposed(shopGPT.destination, shopGPT.sessionId, true);
5464
5631
  document.body.append(shopGPT);
5465
- setShopGPTLoaded(shopGPT.destination, shopGPT.sessionId, true);
5466
5632
  },
5467
5633
  destroy() {
5468
5634
  if (!shopGPT) {
5469
5635
  return;
5470
5636
  }
5471
- setShopGPTLoaded(shopGPT.destination, shopGPT.sessionId, false);
5472
5637
  shopGPT.remove();
5473
5638
  shopGPT = undefined;
5474
5639
  delete window[registryKey];