@envive-ai/react-hooks 0.3.10 → 0.3.12

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 (215) hide show
  1. package/dist/application/commerce-api.cjs +26 -22
  2. package/dist/application/commerce-api.d.cts +58 -0
  3. package/dist/application/commerce-api.d.ts +59 -0
  4. package/dist/application/commerce-api.js +16 -12
  5. package/dist/application/models/api/widgetText.d.cts +14 -0
  6. package/dist/application/models/api/widgetText.d.ts +14 -0
  7. package/dist/application/models/api/widgetTextRequest.d.cts +16 -0
  8. package/dist/application/models/api/widgetTextRequest.d.ts +16 -0
  9. package/dist/application/models/chatElementDisplayLocationV3.cjs +4 -1
  10. package/dist/application/models/chatElementDisplayLocationV3.d.cts +4 -1
  11. package/dist/application/models/chatElementDisplayLocationV3.d.ts +4 -1
  12. package/dist/application/models/chatElementDisplayLocationV3.js +4 -1
  13. package/dist/application/models/guards/api/index.cjs +7 -7
  14. package/dist/application/models/guards/api/index.js +7 -7
  15. package/dist/application/models/guards/api/isApiFormResponse.cjs +1 -1
  16. package/dist/application/models/guards/api/isApiFormResponse.js +1 -1
  17. package/dist/application/models/guards/api/isApiFormSubmittedResponseAttributes.cjs +1 -1
  18. package/dist/application/models/guards/api/isApiFormSubmittedResponseAttributes.js +1 -1
  19. package/dist/application/models/guards/api/isApiOrderResponseAttributes.cjs +1 -1
  20. package/dist/application/models/guards/api/isApiOrderResponseAttributes.js +1 -1
  21. package/dist/application/models/guards/api/isApiProductResponseAttributes.cjs +1 -1
  22. package/dist/application/models/guards/api/isApiProductResponseAttributes.js +1 -1
  23. package/dist/application/models/guards/api/isApiResponse.cjs +1 -1
  24. package/dist/application/models/guards/api/isApiResponse.js +1 -1
  25. package/dist/application/models/index.cjs +29 -29
  26. package/dist/application/models/index.d.cts +25 -25
  27. package/dist/application/models/index.d.ts +25 -25
  28. package/dist/application/models/index.js +29 -29
  29. package/dist/application/models/validators/validateGraphQLFrontendConfig.cjs +1 -1
  30. package/dist/application/models/validators/validateGraphQLFrontendConfig.js +1 -1
  31. package/dist/application/models/validators/validateResponse.cjs +3 -3
  32. package/dist/application/models/validators/validateResponse.js +3 -3
  33. package/dist/application/models/validators/validateUserEvent.cjs +2 -2
  34. package/dist/application/models/validators/validateUserEvent.js +2 -2
  35. package/dist/application/models/variantInfo/variantInfo.cjs +2 -1
  36. package/dist/application/models/variantInfo/variantInfo.d.cts +6 -1
  37. package/dist/application/models/variantInfo/variantInfo.d.ts +6 -1
  38. package/dist/application/models/variantInfo/variantInfo.js +2 -1
  39. package/dist/application/utils/analyticsUtils.cjs +1 -1
  40. package/dist/application/utils/analyticsUtils.js +1 -1
  41. package/dist/application/utils/nodeSelector.cjs +12 -14
  42. package/dist/application/utils/nodeSelector.js +12 -14
  43. package/dist/application/utils/widgetTextFromApiWidgetTextResponse.cjs +3 -1
  44. package/dist/application/utils/widgetTextFromApiWidgetTextResponse.js +3 -1
  45. package/dist/application/utils/widgetTextRequestToApiRequest.cjs +4 -1
  46. package/dist/application/utils/widgetTextRequestToApiRequest.js +4 -1
  47. package/dist/atoms/app/index.cjs +7 -7
  48. package/dist/atoms/app/index.d.cts +1 -1
  49. package/dist/atoms/app/index.d.ts +8 -8
  50. package/dist/atoms/app/index.js +1 -1
  51. package/dist/atoms/app/variant.cjs +44 -4
  52. package/dist/atoms/app/variant.d.cts +8 -8
  53. package/dist/atoms/app/variant.d.ts +8 -8
  54. package/dist/atoms/app/variant.js +44 -5
  55. package/dist/atoms/chat/chatState.d.cts +18 -18
  56. package/dist/atoms/chat/chatState.d.ts +17 -17
  57. package/dist/atoms/chat/form.cjs +1 -1
  58. package/dist/atoms/chat/form.d.cts +2 -2
  59. package/dist/atoms/chat/form.d.ts +2 -2
  60. package/dist/atoms/chat/form.js +1 -1
  61. package/dist/atoms/chat/index.d.cts +3 -3
  62. package/dist/atoms/chat/index.d.ts +2 -2
  63. package/dist/atoms/chat/lastMessage.d.cts +2 -2
  64. package/dist/atoms/chat/lastMessage.d.ts +2 -2
  65. package/dist/atoms/chat/messageQueue.d.cts +6 -6
  66. package/dist/atoms/chat/messageQueue.d.ts +6 -6
  67. package/dist/atoms/chat/performanceMetrics.d.cts +6 -6
  68. package/dist/atoms/chat/performanceMetrics.d.ts +6 -6
  69. package/dist/atoms/chat/renderedWidgetRefs.d.cts +2 -2
  70. package/dist/atoms/chat/renderedWidgetRefs.d.ts +2 -2
  71. package/dist/atoms/chat/replies.d.cts +3 -3
  72. package/dist/atoms/chat/replies.d.ts +3 -3
  73. package/dist/atoms/chat/suggestions.d.cts +2 -2
  74. package/dist/atoms/chat/suggestions.d.ts +2 -2
  75. package/dist/atoms/envive/enviveConfig.d.cts +19 -0
  76. package/dist/atoms/envive/enviveConfig.d.ts +19 -0
  77. package/dist/atoms/globalSearch/globalSearch.d.cts +5 -5
  78. package/dist/atoms/globalSearch/globalSearch.d.ts +5 -5
  79. package/dist/atoms/org/customerService.d.cts +6 -6
  80. package/dist/atoms/org/customerService.d.ts +6 -6
  81. package/dist/atoms/org/graphqlConfig.d.cts +4 -4
  82. package/dist/atoms/org/graphqlConfig.d.ts +4 -4
  83. package/dist/atoms/org/index.cjs +1 -1
  84. package/dist/atoms/org/index.js +1 -1
  85. package/dist/atoms/org/newOrgConfigAtom.d.cts +2 -2
  86. package/dist/atoms/org/newOrgConfigAtom.d.ts +2 -2
  87. package/dist/atoms/org/orgAnalyticsConfig.d.cts +5 -5
  88. package/dist/atoms/org/orgAnalyticsConfig.d.ts +5 -5
  89. package/dist/atoms/search/chatSearch.cjs +1 -1
  90. package/dist/atoms/search/chatSearch.d.cts +17 -17
  91. package/dist/atoms/search/chatSearch.d.ts +17 -17
  92. package/dist/atoms/search/chatSearch.js +1 -1
  93. package/dist/atoms/search/searchAPI.d.cts +13 -13
  94. package/dist/atoms/search/searchAPI.d.ts +13 -13
  95. package/dist/atoms/search/types.d.cts +1 -1
  96. package/dist/atoms/search/types.d.ts +1 -1
  97. package/dist/atoms/search/utils.d.cts +1 -1
  98. package/dist/atoms/search/utils.d.ts +1 -1
  99. package/dist/atoms/widget/chatPreviewLoading.d.cts +2 -2
  100. package/dist/atoms/widget/chatPreviewLoading.d.ts +2 -2
  101. package/dist/config/locators/components/search/index.d.cts +1 -1
  102. package/dist/contexts/amplitudeContext/amplitudeContext.cjs +9 -7
  103. package/dist/contexts/amplitudeContext/amplitudeContext.d.cts +2 -2
  104. package/dist/contexts/amplitudeContext/amplitudeContext.d.ts +2 -2
  105. package/dist/contexts/amplitudeContext/amplitudeContext.js +5 -3
  106. package/dist/contexts/amplitudeContext/index.cjs +1 -0
  107. package/dist/contexts/amplitudeContext/index.d.cts +2 -2
  108. package/dist/contexts/amplitudeContext/index.d.ts +2 -2
  109. package/dist/contexts/amplitudeContext/index.js +2 -2
  110. package/dist/contexts/cdnContext/cdnContext.cjs +3 -3
  111. package/dist/contexts/enviveConfigContext/enviveConfigContext.cjs +6 -5
  112. package/dist/contexts/enviveConfigContext/enviveConfigContext.d.cts +2 -1
  113. package/dist/contexts/enviveConfigContext/enviveConfigContext.d.ts +2 -1
  114. package/dist/contexts/enviveConfigContext/enviveConfigContext.js +3 -2
  115. package/dist/contexts/enviveContext/WindowChatToggleBinder.cjs +4 -3
  116. package/dist/contexts/enviveContext/WindowChatToggleBinder.js +4 -3
  117. package/dist/contexts/enviveContext/enviveContext.cjs +23 -16
  118. package/dist/contexts/enviveContext/enviveContext.d.cts +5 -1
  119. package/dist/contexts/enviveContext/enviveContext.d.ts +5 -1
  120. package/dist/contexts/enviveContext/enviveContext.js +23 -16
  121. package/dist/contexts/enviveContext/types.d.cts +1 -1
  122. package/dist/contexts/enviveContext/types.d.ts +1 -1
  123. package/dist/contexts/featureFlagServiceContext/featureFlagServiceContext.cjs +23 -2
  124. package/dist/contexts/featureFlagServiceContext/featureFlagServiceContext.d.cts +11 -2
  125. package/dist/contexts/featureFlagServiceContext/featureFlagServiceContext.d.ts +11 -2
  126. package/dist/contexts/featureFlagServiceContext/featureFlagServiceContext.js +23 -2
  127. package/dist/contexts/featureFlagServiceContext/index.d.cts +2 -2
  128. package/dist/contexts/featureFlagServiceContext/index.d.ts +2 -2
  129. package/dist/contexts/graphqlContext/graphqlContext.cjs +7 -7
  130. package/dist/contexts/graphqlContext/graphqlContext.d.cts +1 -1
  131. package/dist/contexts/graphqlContext/graphqlContext.d.ts +1 -1
  132. package/dist/contexts/graphqlContext/graphqlContext.js +3 -3
  133. package/dist/contexts/graphqlContext/mockV3Config.cjs +10 -4
  134. package/dist/contexts/graphqlContext/mockV3Config.js +10 -4
  135. package/dist/contexts/hardcopyContext/hardcopyContext.cjs +60 -6
  136. package/dist/contexts/hardcopyContext/hardcopyContext.d.cts +8 -3
  137. package/dist/contexts/hardcopyContext/hardcopyContext.d.ts +8 -3
  138. package/dist/contexts/hardcopyContext/hardcopyContext.js +58 -4
  139. package/dist/contexts/newOrgConfigContext/newOrgConfigContext.cjs +3 -3
  140. package/dist/contexts/pageContext/mapping.cjs +6 -2
  141. package/dist/contexts/pageContext/mapping.js +6 -2
  142. package/dist/contexts/pageContext/pageContext.cjs +12 -7
  143. package/dist/contexts/pageContext/pageContext.js +10 -5
  144. package/dist/contexts/pageContext/types.d.cts +7 -3
  145. package/dist/contexts/pageContext/types.d.ts +7 -3
  146. package/dist/contexts/salesAgentContext/chatAPI.cjs +101 -12
  147. package/dist/contexts/salesAgentContext/chatAPI.d.cts +8 -4
  148. package/dist/contexts/salesAgentContext/chatAPI.d.ts +8 -4
  149. package/dist/contexts/salesAgentContext/chatAPI.js +103 -14
  150. package/dist/contexts/salesAgentContext/salesAgentContext.cjs +1 -1
  151. package/dist/contexts/salesAgentContext/salesAgentContext.js +1 -1
  152. package/dist/contexts/salesAgentContext/salesAgentService.cjs +52 -10
  153. package/dist/contexts/salesAgentContext/salesAgentService.js +50 -8
  154. package/dist/contexts/searchContext/searchContext.cjs +4 -4
  155. package/dist/contexts/searchContext/searchContext.js +1 -1
  156. package/dist/contexts/systemSettingsContext/systemSettingsContext.cjs +3 -3
  157. package/dist/contexts/systemSettingsContext/systemSettingsContext.d.cts +2 -2
  158. package/dist/contexts/types.cjs +1 -1
  159. package/dist/contexts/types.d.cts +10 -3
  160. package/dist/contexts/types.d.ts +10 -3
  161. package/dist/contexts/types.js +1 -1
  162. package/dist/contexts/typesV3.cjs +2 -1
  163. package/dist/contexts/typesV3.d.cts +28 -7
  164. package/dist/contexts/typesV3.d.ts +26 -5
  165. package/dist/contexts/typesV3.js +2 -1
  166. package/dist/contexts/userIdentityContext/userIdentityContext.cjs +3 -3
  167. package/dist/contexts/widgetConfigContext/widgetConfigContext.cjs +1 -1
  168. package/dist/contexts/widgetConfigContext/widgetConfigContext.js +1 -1
  169. package/dist/hooks/AppDetails/useAppDetails.cjs +6 -6
  170. package/dist/hooks/GrabAndScroll/useGrabAndScroll.d.cts +2 -2
  171. package/dist/hooks/ImageResolver/useImageResolver.cjs +3 -3
  172. package/dist/hooks/Search/useSearch.cjs +4 -4
  173. package/dist/hooks/Search/useSearch.d.cts +1 -1
  174. package/dist/hooks/Search/useSearch.d.ts +1 -1
  175. package/dist/hooks/Search/useSearch.js +1 -1
  176. package/dist/services/amplitudeService/amplitudeService.cjs +49 -11
  177. package/dist/services/amplitudeService/amplitudeService.d.cts +18 -3
  178. package/dist/services/amplitudeService/amplitudeService.d.ts +18 -3
  179. package/dist/services/amplitudeService/amplitudeService.js +49 -12
  180. package/dist/services/amplitudeService/index.cjs +1 -0
  181. package/dist/services/amplitudeService/index.d.cts +2 -2
  182. package/dist/services/amplitudeService/index.d.ts +2 -2
  183. package/dist/services/amplitudeService/index.js +2 -2
  184. package/dist/types/customerService.d.cts +3 -1
  185. package/dist/types/customerService.d.ts +1 -1
  186. package/dist/types/enviveConfig.d.cts +4 -1
  187. package/dist/types/enviveConfig.d.ts +4 -1
  188. package/package.json +10 -2
  189. package/src/application/commerce-api.ts +25 -20
  190. package/src/application/models/api/widgetText.ts +2 -0
  191. package/src/application/models/api/widgetTextRequest.ts +2 -0
  192. package/src/application/models/chatElementDisplayLocationV3.ts +3 -0
  193. package/src/application/models/variantInfo/variantInfo.ts +5 -0
  194. package/src/application/utils/nodeSelector.ts +15 -14
  195. package/src/application/utils/widgetTextFromApiWidgetTextResponse.ts +2 -0
  196. package/src/application/utils/widgetTextRequestToApiRequest.ts +5 -0
  197. package/src/atoms/app/variant.ts +56 -2
  198. package/src/contexts/amplitudeContext/__tests__/amplitudeContext.test.tsx +2 -0
  199. package/src/contexts/amplitudeContext/amplitudeContext.tsx +5 -1
  200. package/src/contexts/enviveConfigContext/enviveConfigContext.tsx +3 -0
  201. package/src/contexts/enviveContext/WindowChatToggleBinder.tsx +5 -1
  202. package/src/contexts/enviveContext/enviveContext.tsx +10 -3
  203. package/src/contexts/featureFlagServiceContext/featureFlagServiceContext.tsx +36 -0
  204. package/src/contexts/graphqlContext/mockV3Config.ts +13 -7
  205. package/src/contexts/hardcopyContext/hardcopyContext.tsx +67 -4
  206. package/src/contexts/pageContext/mapping.ts +13 -1
  207. package/src/contexts/pageContext/pageContext.tsx +9 -4
  208. package/src/contexts/pageContext/types.ts +7 -1
  209. package/src/contexts/salesAgentContext/chatAPI.ts +105 -13
  210. package/src/contexts/salesAgentContext/salesAgentService.ts +66 -4
  211. package/src/contexts/types.ts +11 -2
  212. package/src/contexts/typesV3.ts +42 -16
  213. package/src/services/amplitudeService/__tests__/amplitudeService.test.ts +80 -0
  214. package/src/services/amplitudeService/amplitudeService.ts +55 -11
  215. package/src/types/enviveConfig.ts +3 -0
@@ -31,6 +31,9 @@ export const coreWidgetTypeToApiWidgetType = (coreWidgetType: WidgetTypeV3): Wid
31
31
  return WidgetType.FloatingButtonV3;
32
32
  case WidgetTypeV3.PromptButtonCarouselWithImageV3:
33
33
  return WidgetType.SingleImagePromptV3;
34
+ // TODO: Temporary hack to make it work with FPSA.
35
+ case WidgetTypeV3.FullPageSalesAgentV3:
36
+ return WidgetType.FloatingChatV3;
34
37
  default:
35
38
  throw new Error(`Unsupported widget type: ${coreWidgetType}`);
36
39
  }
@@ -39,9 +42,11 @@ export const coreWidgetTypeToApiWidgetType = (coreWidgetType: WidgetTypeV3): Wid
39
42
  export const coreWidgetTextRequestToApiRequest = (
40
43
  coreWidgetTextRequest: CoreWidgetTextRequest,
41
44
  ): ApiWidgetTextRequest => ({
45
+ id: coreWidgetTextRequest.requestId,
42
46
  context: coreContextToApiContext(coreWidgetTextRequest.context),
43
47
  feature_flags: coreWidgetTextRequest.featureFlags,
44
48
  language: coreWidgetTextRequest.language,
45
49
  url: coreWidgetTextRequest.url,
50
+ org_base_config_version: coreWidgetTextRequest.overrideConfigVersion,
46
51
  widget_type: coreWidgetTypeToApiWidgetType(coreWidgetTextRequest.widgetType),
47
52
  });
@@ -1,10 +1,10 @@
1
- import { atomWithStorage } from 'jotai/utils';
2
- import { atom } from 'jotai';
3
1
  import {
4
2
  UserEvent as ApiUserEvent,
5
3
  PageVisitCategory,
6
4
  SupportedEventResponse,
7
5
  } from '@spiffy-ai/commerce-api-client';
6
+ import { atom } from 'jotai';
7
+ import { atomWithStorage } from 'jotai/utils';
8
8
  import {
9
9
  PDPVariantInfo,
10
10
  PLPVariantInfo,
@@ -15,6 +15,8 @@ import {
15
15
  } from 'src/application/models';
16
16
  import { sessionStorageUtil } from 'src/atoms/atomStore';
17
17
  import type { PageVariantInfo } from 'src/contexts/pageContext/types';
18
+ import Logger from 'src/application/logging/logger';
19
+ import { ShowFloatingButtonOptions } from 'src/contexts/types';
18
20
 
19
21
  export interface SupportedEvent extends Pick<
20
22
  SupportedEventResponse,
@@ -167,6 +169,7 @@ const internalPlpIdAtom = atom<string>();
167
169
  const internalUrlAtom = atom<string>();
168
170
  const internalPageVisitCategoryAtom = atom<PageVisitCategory>();
169
171
  const internalVariantAtom = atom<'pdp' | 'plp' | 'search' | 'page_visit'>('pdp');
172
+ const internalFloatingButtonOverrideAtom = atom<ShowFloatingButtonOptions>();
170
173
 
171
174
  export const variantIdAtom = atom(get => get(internalVariantIdAtom));
172
175
  export const productIdAtom = atom(get => get(internalProductIdAtom));
@@ -176,11 +179,13 @@ export const plpIdAtom = atom(get => get(internalPlpIdAtom));
176
179
  export const urlAtom = atom(get => get(internalUrlAtom));
177
180
  export const pageVisitCategoryAtom = atom(get => get(internalPageVisitCategoryAtom));
178
181
  export const variantAtom = atom(get => get(internalVariantAtom));
182
+ export const floatingButtonOverrideAtom = atom(get => get(internalFloatingButtonOverrideAtom));
179
183
  export const hasParsedVariantInfoAtom = atom(false);
180
184
 
181
185
  export const variantInfoAtom = atom(
182
186
  (get): VariantInfo => {
183
187
  const variant = get(variantAtom);
188
+ // TODO: Maybe I need to return the fbo here too.
184
189
  if (variant === VariantTypeEnum.Pdp) {
185
190
  return {
186
191
  variantId: get(variantIdAtom),
@@ -188,6 +193,7 @@ export const variantInfoAtom = atom(
188
193
  productId: get(productIdAtom),
189
194
  parentProductId: get(parentProductIdAtom),
190
195
  url: get(urlAtom),
196
+ floatingButtonOverride: get(floatingButtonOverrideAtom),
191
197
  } as PDPVariantInfo;
192
198
  }
193
199
  if (variant === VariantTypeEnum.Plp) {
@@ -196,6 +202,7 @@ export const variantInfoAtom = atom(
196
202
  variant,
197
203
  plpId: get(plpIdAtom),
198
204
  url: get(urlAtom),
205
+ floatingButtonOverride: get(floatingButtonOverrideAtom),
199
206
  } as PLPVariantInfo;
200
207
  }
201
208
  if (variant === VariantTypeEnum.PageVisit) {
@@ -204,6 +211,7 @@ export const variantInfoAtom = atom(
204
211
  variant,
205
212
  url: get(urlAtom),
206
213
  pageVisitCategory: get(pageVisitCategoryAtom),
214
+ floatingButtonOverride: get(floatingButtonOverrideAtom),
207
215
  } as PageVisitVariantInfo;
208
216
  }
209
217
  throw new Error('Invalid variantInfo details');
@@ -211,6 +219,7 @@ export const variantInfoAtom = atom(
211
219
  (_, set, newVariant: VariantInfo) => {
212
220
  set(internalVariantAtom, newVariant.variant);
213
221
  set(internalVariantIdAtom, newVariant.variantId);
222
+ set(internalFloatingButtonOverrideAtom, newVariant.floatingButtonOverride);
214
223
  if (newVariant.variant === VariantTypeEnum.Pdp) {
215
224
  set(internalProductIdAtom, newVariant.productId);
216
225
  set(internalParentProductIdAtom, newVariant.parentProductId);
@@ -227,6 +236,51 @@ export const variantInfoAtom = atom(
227
236
  },
228
237
  );
229
238
 
239
+ const getPageVisitContext = (pageVisitCategory: PageVisitCategory | undefined) => {
240
+ if (pageVisitCategory === PageVisitCategory.Search) {
241
+ const searchParams = new URLSearchParams(window.location.search);
242
+ const searchTerm = searchParams.get('esq');
243
+ return {
244
+ page_type: 'search',
245
+ page_id: searchTerm,
246
+ };
247
+ }
248
+ if (pageVisitCategory === PageVisitCategory.Homepage) {
249
+ return {
250
+ page_type: 'homepage',
251
+ page_id: window.location.href,
252
+ };
253
+ }
254
+ return {
255
+ page_type: 'other',
256
+ page_id: window.location.href,
257
+ };
258
+ };
259
+
260
+ export const analyticsContextAtom = atom(get => {
261
+ const variantInfo = get(variantInfoAtom);
262
+ if (variantInfo.variant === VariantTypeEnum.Pdp) {
263
+ return {
264
+ page_type: 'pdp',
265
+ page_id: variantInfo.productId,
266
+ };
267
+ }
268
+ if (variantInfo.variant === VariantTypeEnum.Plp) {
269
+ return {
270
+ page_type: 'plp',
271
+ page_id: variantInfo.plpId,
272
+ };
273
+ }
274
+ if (variantInfo.variant === VariantTypeEnum.PageVisit) {
275
+ return getPageVisitContext(variantInfo.pageVisitCategory);
276
+ }
277
+ Logger.logWarn('[envive-ai] Invalid variantInfo', undefined, { variantInfo });
278
+ return {
279
+ page_type: 'other',
280
+ page_id: window.location.href,
281
+ };
282
+ });
283
+
230
284
  // Atoms for page context - can be set directly by PageProvider or for storybook/testing
231
285
  export const pageUserEventAtom = atom<UserEvent | undefined>(undefined);
232
286
  export const pageVariantInfoAtom = atom<PageVariantInfo | undefined>(undefined);
@@ -376,6 +376,7 @@ describe('AmplitudeProvider - React Context Integration', () => {
376
376
  dataResidency: 'EU',
377
377
  orgId: 'test-org-id',
378
378
  show: true,
379
+ enviveOn: true,
379
380
  getLocalStorageItem: mockGetLocalStorageItem,
380
381
  featureFlagService: new FeatureFlagService([]),
381
382
  env: 'test', // Provide required fields to match AmplitudeServiceConfig
@@ -415,6 +416,7 @@ describe('AmplitudeProvider - React Context Integration', () => {
415
416
  dataResidency: 'EU',
416
417
  orgId: 'test-org-id',
417
418
  show: true,
419
+ enviveOn: true,
418
420
  getLocalStorageItem: mockGetLocalStorageItem,
419
421
  featureFlagService: new FeatureFlagService([]),
420
422
  env: 'test',
@@ -13,11 +13,12 @@ import { useEnviveConfig } from 'src/contexts/enviveConfigContext/enviveConfigCo
13
13
  import { useFeatureFlagService } from 'src/contexts/featureFlagServiceContext/featureFlagServiceContext';
14
14
  import {
15
15
  AmplitudeService,
16
+ EnviveMetricsEventName,
16
17
  SpiffyMetricsEventName,
17
18
  TrackEventParams,
18
19
  } from 'src/services/amplitudeService/amplitudeService';
19
20
 
20
- export { SpiffyMetricsEventName };
21
+ export { EnviveMetricsEventName, SpiffyMetricsEventName };
21
22
 
22
23
  interface AmplitudeContextType {
23
24
  trackEvent: (params: TrackEventParams) => Promise<void>;
@@ -43,6 +44,7 @@ export const AmplitudeProvider: React.FC<{
43
44
  variantUrlOverride,
44
45
  variantInfoOverride,
45
46
  show,
47
+ enviveOn,
46
48
  orgId,
47
49
  orgShortName,
48
50
  featureGates,
@@ -72,6 +74,7 @@ export const AmplitudeProvider: React.FC<{
72
74
  featureFlagService,
73
75
  orgGaConfig,
74
76
  show: show ?? false,
77
+ enviveOn: enviveOn ?? false,
75
78
  getLocalStorageItem: getItem,
76
79
  });
77
80
  setService(amplitudeService);
@@ -91,6 +94,7 @@ export const AmplitudeProvider: React.FC<{
91
94
  variantUrlOverride,
92
95
  variantInfoOverride,
93
96
  show,
97
+ enviveOn,
94
98
  featureGates,
95
99
  getItem,
96
100
  externalAmplitudeService,
@@ -24,6 +24,7 @@ interface EnviveConfigProviderProps {
24
24
  variantUrlOverride?: string;
25
25
  variantInfoOverride?: any;
26
26
  show?: boolean;
27
+ enviveOn?: boolean;
27
28
  publicKey?: string;
28
29
  featureGates?: OrgConfigFeatureGate[]; // New prop for feature gates
29
30
  }
@@ -45,6 +46,7 @@ export const EnviveConfigProvider: React.FC<EnviveConfigProviderProps> = ({
45
46
  variantUrlOverride,
46
47
  variantInfoOverride,
47
48
  show,
49
+ enviveOn,
48
50
  publicKey,
49
51
  featureGates, // Destructure new prop
50
52
  }) => {
@@ -66,6 +68,7 @@ export const EnviveConfigProvider: React.FC<EnviveConfigProviderProps> = ({
66
68
  variantUrlOverride,
67
69
  variantInfoOverride,
68
70
  show,
71
+ enviveOn,
69
72
  publicKey,
70
73
  featureGates, // Add to config
71
74
  };
@@ -25,7 +25,11 @@ export const WindowChatToggleBinder = () => {
25
25
  toggleChatRef.current = (triggerId?: string) => hook.toggle(triggerLocation, triggerId);
26
26
  isOpenRef.current = hook.isOpen;
27
27
  openChatWithPromptRef.current = (prompt: string, triggerId?: string) => {
28
- onTypedMessageSubmitted({ query: prompt, userTyped: false });
28
+ onTypedMessageSubmitted({
29
+ query: prompt,
30
+ userTyped: false,
31
+ displayLocation: ChatElementDisplayLocationV3.WINDOW_API_CALL,
32
+ });
29
33
  hook.openChat(triggerLocation, triggerId);
30
34
  };
31
35
  }, [hook, onTypedMessageSubmitted, triggerLocation]);
@@ -17,7 +17,8 @@ import { EnviveAgent } from './types';
17
17
  import { SearchProvider } from '../searchContext';
18
18
  import { SalesAgentProvider } from '../salesAgentContext/salesAgentContext';
19
19
  import { SystemSettingsContextProvider } from '../systemSettingsContext';
20
- import { HardcopyProvider } from '../hardcopyContext';
20
+ import { HardcopyProvider, HardcopyResponse } from '../hardcopyContext';
21
+ import { WidgetTypeV3 } from '../typesV3';
21
22
  import { WidgetConfigProvider } from '../widgetConfigContext';
22
23
  import { PageProvider } from '../pageContext';
23
24
  import { UiConfigProvider } from '../uiConfigContext';
@@ -45,6 +46,7 @@ interface EnviveProviderProps extends AgentWrapperProps {
45
46
  variantUrlOverride?: string;
46
47
  variantInfoOverride?: any;
47
48
  show?: boolean;
49
+ enviveOn?: boolean;
48
50
  publicKey?: string;
49
51
  featureGates?: OrgConfigFeatureGate[]; // New prop for feature gates
50
52
  featureFlagService?: FeatureFlagService;
@@ -56,6 +58,7 @@ interface EnviveProviderProps extends AgentWrapperProps {
56
58
  previewMode?: boolean;
57
59
  overrideConfig?: GraphQlConfigValues;
58
60
  mockSalesAgentData?: any;
61
+ hardcopyOverride?: Partial<Record<WidgetTypeV3, HardcopyResponse>>;
59
62
  }
60
63
 
61
64
  const SearchAgentWrapper: React.FC<AgentWrapperProps> = ({ children, enabledAgents }) => {
@@ -67,6 +70,7 @@ const SearchAgentWrapper: React.FC<AgentWrapperProps> = ({ children, enabledAgen
67
70
 
68
71
  interface SalesAgentWrapperProps extends AgentWrapperProps {
69
72
  previewMode?: boolean;
73
+ showDebugBar: boolean;
70
74
  mockSalesAgentData?: any;
71
75
  }
72
76
 
@@ -74,13 +78,14 @@ const SalesAgentWrapper: React.FC<SalesAgentWrapperProps> = ({
74
78
  children,
75
79
  enabledAgents,
76
80
  previewMode,
81
+ showDebugBar,
77
82
  mockSalesAgentData,
78
83
  }) => {
79
84
  if (!enabledAgents.includes(EnviveAgent.SalesAgent)) {
80
85
  return children;
81
86
  }
82
87
  return (
83
- <SystemSettingsContextProvider>
88
+ <SystemSettingsContextProvider showDebugBar={showDebugBar}>
84
89
  <SalesAgentProvider
85
90
  previewMode={previewMode}
86
91
  mockData={mockSalesAgentData}
@@ -103,6 +108,7 @@ export const EnviveProvider: React.FC<EnviveProviderProps> = ({
103
108
  mockV3ConfigToDeprecatedConfig = false,
104
109
  requestV3Config = false,
105
110
  mockSalesAgentData,
111
+ hardcopyOverride,
106
112
  ...config
107
113
  }) => {
108
114
  const [userId, setUserId] = useState<string>('');
@@ -181,12 +187,13 @@ export const EnviveProvider: React.FC<EnviveProviderProps> = ({
181
187
  <PageProvider previewMode={previewMode}>
182
188
  <UiConfigProvider>
183
189
  <WidgetConfigProvider>
184
- <HardcopyProvider>
190
+ <HardcopyProvider hardcopyOverride={hardcopyOverride}>
185
191
  <EnviveCssProvider>
186
192
  <SearchAgentWrapper enabledAgents={enabledAgents}>
187
193
  <WindowChatToggleBinder />
188
194
  <SalesAgentWrapper
189
195
  enabledAgents={enabledAgents}
196
+ showDebugBar={config.enviveOn || false}
190
197
  previewMode={previewMode}
191
198
  mockSalesAgentData={mockSalesAgentData}
192
199
  >
@@ -5,6 +5,14 @@ import Logger from 'src/application/logging/logger';
5
5
 
6
6
  const FEATURE_FLAGS_STORAGE_KEY = 'spiffy-feature-flags';
7
7
 
8
+ export interface FullFlagValue {
9
+ resolved: boolean;
10
+ initial: boolean | undefined;
11
+ query_param_override: boolean | undefined;
12
+ window_param_override: boolean | undefined;
13
+ stored_override: boolean | undefined;
14
+ }
15
+
8
16
  // This is the class that was previously implicitly used or defined elsewhere
9
17
  export class FeatureFlagService {
10
18
  private featureGates: OrgConfigFeatureGate[];
@@ -124,6 +132,34 @@ export class FeatureFlagService {
124
132
  );
125
133
  };
126
134
 
135
+ getFullFlagValue = (featureGate: FeatureGates): FullFlagValue => {
136
+ const gateValue = this.featureGates.find(gate => gate.name === featureGate);
137
+ return {
138
+ resolved: this.isFeatureGateEnabled(featureGate),
139
+ initial: gateValue?.value,
140
+ query_param_override: FeatureFlagService.getQueryParamFeatureGateOverrides(featureGate),
141
+ window_param_override: FeatureFlagService.getWindowFeatureGateOverrides(featureGate),
142
+ stored_override: FeatureFlagService.getStoredFeatureGateOverrides(featureGate),
143
+ };
144
+ };
145
+
146
+ getFullFlagValues = (): Record<string, FullFlagValue> => {
147
+ const featureGates = Object.values(FeatureGates).map((featureGate: FeatureGates) => [
148
+ featureGate,
149
+ this.getFullFlagValue(featureGate),
150
+ ]);
151
+
152
+ return featureGates.length > 0
153
+ ? featureGates.reduce<Record<string, FullFlagValue>>((acc, entry) => {
154
+ const [name, value] = entry as [FeatureGates, FullFlagValue];
155
+ if (name && value != null) {
156
+ return { ...acc, [`feature_gate.${name}`]: value };
157
+ }
158
+ return acc;
159
+ }, {})
160
+ : {};
161
+ };
162
+
127
163
  static persistFeatureGateOverrides(): void {
128
164
  if (typeof window === 'undefined' || typeof window.localStorage === 'undefined') {
129
165
  return;
@@ -1,17 +1,17 @@
1
- import { FrontendConfigV3 } from 'src/application/models/frontendConfigV3';
2
- import { ColorMappingV3, ColorNames, colorVar } from 'src/application/models/colorsConfigV3';
3
- import { CamelCasedPropertiesDeep } from 'src/application/models';
1
+ import { ChatHeaderVariant } from '@envive-ai/react-toolkit-v3/ChatHeader';
4
2
  import { ImageGalleryLayout } from '@envive-ai/react-toolkit-v3/ImageGallery';
5
3
  import { PromptButtonVariant } from '@envive-ai/react-toolkit-v3/PromptButton';
6
4
  import { AnimationSpeed, PromptCarouselRows } from '@envive-ai/react-toolkit-v3/PromptCarousel';
7
- import { WidgetWrapperVariant } from '@envive-ai/react-toolkit-v3/WidgetWrapper';
8
- import { Theme } from '@envive-ai/react-toolkit-v3/Tokens';
9
- import { ChatHeaderVariant } from '@envive-ai/react-toolkit-v3/ChatHeader';
10
5
  import { WidgetKind } from '@envive-ai/react-toolkit-v3/SocialProof';
6
+ import { Theme } from '@envive-ai/react-toolkit-v3/Tokens';
11
7
  import { SparkleIconColor } from '@envive-ai/react-toolkit-v3/WelcomeMessage';
8
+ import { WidgetWrapperVariant } from '@envive-ai/react-toolkit-v3/WidgetWrapper';
9
+ import { CamelCasedPropertiesDeep } from 'src/application/models';
10
+ import { ColorMappingV3, ColorNames, colorVar } from 'src/application/models/colorsConfigV3';
11
+ import { FrontendConfigV3 } from 'src/application/models/frontendConfigV3';
12
12
 
13
- import { CustomerServiceType } from 'src/types/customerService';
14
13
  import { FloatingButtonLocation } from '@envive-ai/react-toolkit-v3/FloatingButton';
14
+ import { CustomerServiceType } from 'src/types/customerService';
15
15
  import { ConfigVersionEnum, WidgetTypeV3 } from '../typesV3';
16
16
 
17
17
  const mockImages = [
@@ -262,5 +262,11 @@ export const mockV3FrontendConfig: FrontendConfigV3 = {
262
262
  imageSrc:
263
263
  'https://www.bandolierstyle.com/cdn/shop/files/Lily17_Black_Gold_Chrome_MOD_Dec25_6.jpg?v=1765844272',
264
264
  },
265
+ 'full-page-sales-agent-widget': {
266
+ widgetConfigId: 'full-page-sales-agent-widget',
267
+ contentId: 'full-page-sales-agent-widget',
268
+ type: WidgetTypeV3.FullPageSalesAgentV3,
269
+ autoHeight: true,
270
+ },
265
271
  },
266
272
  };
@@ -1,16 +1,19 @@
1
1
  import { ReactNode, createContext, useCallback, useContext, useMemo, useState } from 'react';
2
2
  import Logger from 'src/application/logging/logger';
3
-
3
+ import { v4 as uuid } from 'uuid';
4
4
  import CommerceApiClient from 'src/application/commerce-api';
5
- import { WidgetText } from 'src/application/models/api/widgetText';
5
+ import { WidgetString, WidgetText } from 'src/application/models/api/widgetText';
6
6
  import { WidgetTextRequest } from 'src/application/models/api/widgetTextRequest';
7
7
 
8
8
  import { useAtomValue } from 'jotai';
9
9
  import { appDetailsAtom } from 'src/atoms/app';
10
+ import { EnviveMetricsEventName } from 'src/services/amplitudeService/amplitudeService';
10
11
  import { toCamelCase } from 'src/application/models/utils/snakeToCamelTransformer';
11
12
  import { UserEvent } from 'src/application/models';
13
+ import { getQueryParam } from 'src/application/utils';
12
14
  import { WidgetTypeV3 } from '../typesV3';
13
15
  import { useFeatureFlagService } from '../featureFlagServiceContext/featureFlagServiceContext';
16
+ import { useAmplitude } from '../amplitudeContext';
14
17
 
15
18
  interface HardcopyRequest {
16
19
  widgetType: WidgetTypeV3;
@@ -18,7 +21,9 @@ interface HardcopyRequest {
18
21
  }
19
22
 
20
23
  export type HardcopyResponse = {
24
+ responseId: string;
21
25
  language: string;
26
+ rawValues?: Record<string, WidgetString | WidgetString[]>;
22
27
  values: Record<string, string | string[]>;
23
28
  };
24
29
 
@@ -29,7 +34,9 @@ interface HardcopyContextType {
29
34
 
30
35
  const convertToHardcopyResponse = (response: WidgetText): HardcopyResponse => {
31
36
  return {
37
+ responseId: response.responseId,
32
38
  language: response.language,
39
+ rawValues: response.values,
33
40
  values: Object.fromEntries(
34
41
  Object.entries(response.values).map(([key, value]) => [
35
42
  // Transform the key from snake_case to camelCase
@@ -45,6 +52,7 @@ const convertToHardcopyResponse = (response: WidgetText): HardcopyResponse => {
45
52
  // values and their names should be.
46
53
  const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> = {
47
54
  [WidgetTypeV3.PromptCarouselV3]: {
55
+ responseId: uuid(),
48
56
  language: 'en',
49
57
  values: {
50
58
  promptButtonTexts: [
@@ -57,6 +65,7 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
57
65
  },
58
66
  },
59
67
  [WidgetTypeV3.TitledPromptCarouselV3]: {
68
+ responseId: 'mock-response-id',
60
69
  language: 'en',
61
70
  values: {
62
71
  titleLabel: 'Need some help?',
@@ -70,6 +79,7 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
70
79
  },
71
80
  },
72
81
  [WidgetTypeV3.SocialProofV3]: {
82
+ responseId: 'mock-response-id',
73
83
  language: 'en',
74
84
  values: {
75
85
  titleLabel: 'Shopping Assistant',
@@ -88,6 +98,7 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
88
98
  },
89
99
  },
90
100
  [WidgetTypeV3.TypingAnimationV3]: {
101
+ responseId: 'mock-response-id',
91
102
  language: 'en',
92
103
  values: {
93
104
  titleLabel: 'Shopping Assistant',
@@ -108,6 +119,7 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
108
119
  },
109
120
  },
110
121
  [WidgetTypeV3.ChatPreviewComparisonV3]: {
122
+ responseId: 'mock-response-id',
111
123
  language: 'en',
112
124
  values: {
113
125
  titleLabel: 'Shopping Assistant',
@@ -116,6 +128,7 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
116
128
  },
117
129
  },
118
130
  [WidgetTypeV3.ChatPreviewLoadingV3]: {
131
+ responseId: 'mock-response-id',
119
132
  language: 'en',
120
133
  values: {
121
134
  titleLabel: 'Shopping Assistant',
@@ -123,6 +136,7 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
123
136
  },
124
137
  },
125
138
  [WidgetTypeV3.ChatPreviewV3]: {
139
+ responseId: 'mock-response-id',
126
140
  language: 'en',
127
141
  values: {
128
142
  titleLabel: 'Shopping Assistant',
@@ -130,6 +144,7 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
130
144
  },
131
145
  },
132
146
  [WidgetTypeV3.PromptButtonCarouselWithImageV3]: {
147
+ responseId: 'mock-response-id',
133
148
  language: 'en',
134
149
  values: {
135
150
  titleLabel: 'Need some help?',
@@ -138,6 +153,7 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
138
153
  },
139
154
  },
140
155
  [WidgetTypeV3.ProductCardV3]: {
156
+ responseId: 'mock-response-id',
141
157
  language: 'en',
142
158
  values: {
143
159
  headline: 'Discover Your Perfect Style',
@@ -157,6 +173,18 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
157
173
  },
158
174
  },
159
175
  [WidgetTypeV3.FloatingChatV3]: {
176
+ responseId: 'mock-response-id',
177
+ language: 'en',
178
+ values: {
179
+ welcomeMessageTitle: 'Welcome to Envive AI',
180
+ welcomeMessageText:
181
+ 'Your personal shopper trained on the collective knowledge of thousands of real experts!',
182
+ chatFooterTextFieldPlaceholderText: 'Ask me anything...',
183
+ disclaimerText: 'This is a disclaimer...',
184
+ },
185
+ },
186
+ [WidgetTypeV3.FullPageSalesAgentV3]: {
187
+ responseId: 'mock-response-id',
160
188
  language: 'en',
161
189
  values: {
162
190
  welcomeMessageTitle: 'Welcome to Envive AI',
@@ -170,26 +198,61 @@ const MOCK_HARDCOPY_RESPONSE: Partial<Record<WidgetTypeV3, HardcopyResponse>> =
170
198
 
171
199
  const HardcopyContext = createContext<HardcopyContextType | undefined>(undefined);
172
200
 
173
- export const HardcopyProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
201
+ interface HardcopyProviderProps {
202
+ children: ReactNode;
203
+ hardcopyOverride?: Partial<Record<WidgetTypeV3, HardcopyResponse>>;
204
+ }
205
+
206
+ export const HardcopyProvider: React.FC<HardcopyProviderProps> = ({
207
+ children,
208
+ hardcopyOverride,
209
+ }) => {
174
210
  const languages = useMemo(() => navigator.languages, []);
175
211
  const [isLoading, setIsLoading] = useState(false);
176
212
  const context = useAtomValue(appDetailsAtom);
213
+ const { trackEvent } = useAmplitude();
177
214
 
178
215
  const { featureFlagService } = useFeatureFlagService();
179
216
  const getHardcopyFromBackend = useCallback(
180
217
  async (request: HardcopyRequest): Promise<HardcopyResponse> => {
218
+ if (hardcopyOverride?.[request.widgetType]) {
219
+ Logger.logInfo('hardcopyContext | using hardcopy override', request.widgetType);
220
+ return hardcopyOverride[request.widgetType]!;
221
+ }
222
+ const overrideConfigVersion =
223
+ getQueryParam('spiffy_config_version') ||
224
+ getQueryParam('envive_config_version') ||
225
+ undefined;
181
226
  const widgetTextRequest: WidgetTextRequest = {
227
+ requestId: uuid(),
182
228
  widgetType: request.widgetType,
183
229
  context,
184
230
  featureFlags: featureFlagService?.getFeatureFlags() || {},
185
231
  language: languages[0] || 'en',
232
+ overrideConfigVersion,
186
233
  url: window.location.href,
187
234
  };
235
+ trackEvent({
236
+ eventName: EnviveMetricsEventName.WidgetTextRequest,
237
+ eventProps: {
238
+ widget_type: request.widgetType,
239
+ request_id: widgetTextRequest.requestId,
240
+ },
241
+ });
188
242
  try {
189
243
  const response = await CommerceApiClient.getHardcopy(widgetTextRequest);
190
244
  if (response) {
191
245
  const convertedResponse = convertToHardcopyResponse(response);
192
246
  Logger.logInfo('hardcopyContext | converted response', convertedResponse);
247
+ trackEvent({
248
+ eventName: EnviveMetricsEventName.WidgetTextResponse,
249
+ eventProps: {
250
+ widget_type: request.widgetType,
251
+ response_id: response.responseId,
252
+ widget_text: response.values,
253
+ request_id: widgetTextRequest.requestId,
254
+ },
255
+ });
193
256
  return convertedResponse;
194
257
  }
195
258
  } catch (error) {
@@ -202,7 +265,7 @@ export const HardcopyProvider: React.FC<{ children: ReactNode }> = ({ children }
202
265
  }
203
266
  throw new Error(`No hardcopy response found for widget type: ${request.widgetType}`);
204
267
  },
205
- [context, featureFlagService, languages],
268
+ [context, featureFlagService, hardcopyOverride, languages, trackEvent],
206
269
  );
207
270
 
208
271
  const getHardcopy = useCallback(
@@ -15,7 +15,13 @@ import { isApiSearchAttributes } from 'src/application/models/guards/api/isApiSe
15
15
  import { isApiSuggestionClickedAttributes } from 'src/application/models/guards/api/isApiSuggestionClickedEventAttributes';
16
16
  import { isApiFormSubmittedResponseAttributes } from 'src/application/models/guards/api/isApiFormSubmittedResponseAttributes';
17
17
 
18
- import { HomeVariantInfo, OtherVariantInfo, PageVariantInfo, VisitPageVariantInfo } from './types';
18
+ import {
19
+ FullPageSalesAgentVariantInfo,
20
+ HomeVariantInfo,
21
+ OtherVariantInfo,
22
+ PageVariantInfo,
23
+ VisitPageVariantInfo,
24
+ } from './types';
19
25
 
20
26
  export const mapUrlResolverResponseToVariantInfo = (
21
27
  url: string,
@@ -66,6 +72,12 @@ export const mapUrlResolverResponseToVariantInfo = (
66
72
  } as OtherVariantInfo;
67
73
  }
68
74
 
75
+ if (response.variant_type === VariantTypeEnum.FullPageSalesAgent) {
76
+ return {
77
+ variantType: VariantTypeEnum.FullPageSalesAgent,
78
+ url,
79
+ } as FullPageSalesAgentVariantInfo;
80
+ }
69
81
  throw new Error('Invalid variant type');
70
82
  };
71
83
 
@@ -67,10 +67,15 @@ export const PageProvider: React.FC<{
67
67
 
68
68
  const setVariantFromUrlResolver = useCallback(
69
69
  (url: string, response: UrlResolverResponse) => {
70
- const newVariantInfo = mapUrlResolverResponseToVariantInfo(url, response);
71
- const newUserEvent = mapApiUserEventToUserEvent(response.user_event ?? undefined);
72
- setVariantInfo(newVariantInfo);
73
- setUserEvent(newUserEvent);
70
+ if (response.ready) {
71
+ const newVariantInfo = mapUrlResolverResponseToVariantInfo(url, response);
72
+ const newUserEvent = mapApiUserEventToUserEvent(response.user_event ?? undefined);
73
+ setVariantInfo(newVariantInfo);
74
+ setUserEvent(newUserEvent);
75
+ } else {
76
+ setUserEvent(undefined);
77
+ setVariantInfo(undefined);
78
+ }
74
79
  },
75
80
  [setVariantInfo, setUserEvent],
76
81
  );
@@ -31,12 +31,18 @@ export type OtherVariantInfo = {
31
31
  url: string;
32
32
  };
33
33
 
34
+ export type FullPageSalesAgentVariantInfo = {
35
+ variantType: VariantTypeEnum.FullPageSalesAgent;
36
+ url: string;
37
+ };
38
+
34
39
  export type PageVariantInfo =
35
40
  | PDPPageVariantInfo
36
41
  | PLPPageVariantInfo
37
42
  | VisitPageVariantInfo
38
43
  | HomeVariantInfo
39
- | OtherVariantInfo;
44
+ | OtherVariantInfo
45
+ | FullPageSalesAgentVariantInfo;
40
46
 
41
47
  export interface PageDetails {
42
48
  pageUrl: string | undefined;