@envive-ai/react-hooks 0.3.12 → 0.3.13

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 (167) hide show
  1. package/dist/application/commerce-api.cjs +4 -28
  2. package/dist/application/commerce-api.d.cts +1 -3
  3. package/dist/application/commerce-api.d.ts +1 -3
  4. package/dist/application/commerce-api.js +4 -28
  5. package/dist/application/utils/analyticsUtils.cjs +5 -5
  6. package/dist/application/utils/analyticsUtils.d.cts +2 -2
  7. package/dist/application/utils/analyticsUtils.d.ts +2 -2
  8. package/dist/application/utils/analyticsUtils.js +3 -3
  9. package/dist/atoms/app/index.d.cts +7 -7
  10. package/dist/atoms/app/index.d.ts +7 -7
  11. package/dist/atoms/chat/chatState.cjs +5 -5
  12. package/dist/atoms/chat/chatState.d.cts +19 -19
  13. package/dist/atoms/chat/chatState.d.ts +19 -19
  14. package/dist/atoms/chat/chatState.js +3 -3
  15. package/dist/atoms/chat/form.d.cts +2 -2
  16. package/dist/atoms/chat/form.d.ts +2 -2
  17. package/dist/atoms/chat/index.d.cts +2 -2
  18. package/dist/atoms/chat/lastMessage.d.cts +2 -2
  19. package/dist/atoms/chat/lastMessage.d.ts +2 -2
  20. package/dist/atoms/chat/messageQueue.d.cts +6 -6
  21. package/dist/atoms/chat/messageQueue.d.ts +6 -6
  22. package/dist/atoms/chat/performanceMetrics.d.cts +6 -6
  23. package/dist/atoms/chat/performanceMetrics.d.ts +6 -6
  24. package/dist/atoms/chat/renderedWidgetRefs.d.cts +2 -2
  25. package/dist/atoms/chat/renderedWidgetRefs.d.ts +2 -2
  26. package/dist/atoms/chat/replies.cjs +4 -4
  27. package/dist/atoms/chat/replies.d.cts +3 -3
  28. package/dist/atoms/chat/replies.d.ts +1 -1
  29. package/dist/atoms/chat/replies.js +3 -3
  30. package/dist/atoms/chat/suggestions.d.cts +2 -2
  31. package/dist/atoms/chat/suggestions.d.ts +2 -2
  32. package/dist/atoms/envive/enviveConfig.d.cts +13 -13
  33. package/dist/atoms/envive/enviveConfig.d.ts +1 -1
  34. package/dist/atoms/globalSearch/globalSearch.d.cts +5 -5
  35. package/dist/atoms/globalSearch/globalSearch.d.ts +5 -5
  36. package/dist/atoms/org/customerService.d.cts +6 -6
  37. package/dist/atoms/org/customerService.d.ts +6 -6
  38. package/dist/atoms/org/graphqlConfig.d.cts +4 -4
  39. package/dist/atoms/org/graphqlConfig.d.ts +4 -4
  40. package/dist/atoms/org/index.cjs +1 -1
  41. package/dist/atoms/org/index.js +1 -1
  42. package/dist/atoms/org/newOrgConfigAtom.d.cts +2 -2
  43. package/dist/atoms/org/orgAnalyticsConfig.d.cts +5 -5
  44. package/dist/atoms/search/chatSearch.d.cts +17 -17
  45. package/dist/atoms/search/chatSearch.d.ts +17 -17
  46. package/dist/atoms/search/searchAPI.d.cts +13 -13
  47. package/dist/atoms/search/searchAPI.d.ts +13 -13
  48. package/dist/atoms/search/types.d.cts +1 -1
  49. package/dist/atoms/search/utils.d.cts +1 -1
  50. package/dist/atoms/search/utils.d.ts +1 -1
  51. package/dist/atoms/widget/chatPreviewLoading.d.cts +2 -2
  52. package/dist/atoms/widget/chatPreviewLoading.d.ts +2 -2
  53. package/dist/config/locators/components/search/index.d.cts +1 -1
  54. package/dist/contexts/amplitudeContext/amplitudeContext.cjs +5 -4
  55. package/dist/contexts/amplitudeContext/amplitudeContext.d.cts +3 -2
  56. package/dist/contexts/amplitudeContext/amplitudeContext.d.ts +3 -2
  57. package/dist/contexts/amplitudeContext/amplitudeContext.js +5 -4
  58. package/dist/contexts/amplitudeContext/index.cjs +3 -3
  59. package/dist/contexts/amplitudeContext/index.d.cts +1 -1
  60. package/dist/contexts/amplitudeContext/index.d.ts +1 -1
  61. package/dist/contexts/amplitudeContext/index.js +1 -1
  62. package/dist/contexts/cdnContext/cdnContext.cjs +1 -1
  63. package/dist/contexts/cdnContext/cdnContext.js +1 -1
  64. package/dist/contexts/enviveConfigContext/enviveConfigContext.cjs +1 -1
  65. package/dist/contexts/enviveConfigContext/enviveConfigContext.js +1 -1
  66. package/dist/contexts/enviveContext/types.d.cts +1 -1
  67. package/dist/contexts/graphqlContext/graphqlContext.cjs +2 -2
  68. package/dist/contexts/graphqlContext/graphqlContext.js +2 -2
  69. package/dist/contexts/graphqlContext/mockV3Config.cjs +3 -2
  70. package/dist/contexts/graphqlContext/mockV3Config.js +3 -2
  71. package/dist/contexts/hardcopyContext/hardcopyContext.cjs +9 -8
  72. package/dist/contexts/hardcopyContext/hardcopyContext.js +7 -6
  73. package/dist/contexts/newOrgConfigContext/newOrgConfigContext.cjs +1 -1
  74. package/dist/contexts/newOrgConfigContext/newOrgConfigContext.js +1 -1
  75. package/dist/contexts/pageContext/pageContext.cjs +1 -1
  76. package/dist/contexts/pageContext/pageContext.js +1 -1
  77. package/dist/contexts/salesAgentContext/chatAPI.cjs +11 -10
  78. package/dist/contexts/salesAgentContext/chatAPI.js +4 -3
  79. package/dist/contexts/salesAgentContext/salesAgentContext.cjs +1 -1
  80. package/dist/contexts/salesAgentContext/salesAgentContext.js +1 -1
  81. package/dist/contexts/salesAgentContext/salesAgentService.cjs +9 -8
  82. package/dist/contexts/salesAgentContext/salesAgentService.js +7 -6
  83. package/dist/contexts/searchContext/searchContext.cjs +2 -2
  84. package/dist/contexts/searchContext/searchContext.js +2 -2
  85. package/dist/contexts/systemSettingsContext/systemSettingsContext.cjs +1 -1
  86. package/dist/contexts/systemSettingsContext/systemSettingsContext.js +1 -1
  87. package/dist/contexts/types.d.cts +1 -1
  88. package/dist/contexts/types.d.ts +1 -1
  89. package/dist/contexts/typesV3.cjs +1 -1
  90. package/dist/contexts/typesV3.d.cts +10 -1
  91. package/dist/contexts/typesV3.d.ts +10 -1
  92. package/dist/contexts/typesV3.js +1 -1
  93. package/dist/contexts/userIdentityContext/userIdentityContext.cjs +2 -34
  94. package/dist/contexts/userIdentityContext/userIdentityContext.d.cts +1 -2
  95. package/dist/contexts/userIdentityContext/userIdentityContext.d.ts +1 -2
  96. package/dist/contexts/userIdentityContext/userIdentityContext.js +2 -33
  97. package/dist/hooks/AmplitudeOperations/useAmplitudeOperations.cjs +1 -1
  98. package/dist/hooks/AmplitudeOperations/useAmplitudeOperations.d.cts +2 -2
  99. package/dist/hooks/AmplitudeOperations/useAmplitudeOperations.d.ts +2 -2
  100. package/dist/hooks/AmplitudeOperations/useAmplitudeOperations.js +1 -1
  101. package/dist/hooks/ChatToggle/useChatToggle.cjs +6 -5
  102. package/dist/hooks/ChatToggle/useChatToggle.js +4 -3
  103. package/dist/hooks/GrabAndScroll/useGrabAndScroll.d.cts +2 -2
  104. package/dist/hooks/Search/useSearch.cjs +9 -8
  105. package/dist/hooks/Search/useSearch.js +4 -3
  106. package/dist/hooks/Search/useSearchInput.cjs +6 -6
  107. package/dist/hooks/Search/useSearchInput.js +3 -3
  108. package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.cjs +6 -5
  109. package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.d.cts +2 -2
  110. package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.d.ts +2 -2
  111. package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.js +3 -2
  112. package/dist/hooks/UpdateAnalyticsProps/useUpdateAnalyticsProps.cjs +4 -3
  113. package/dist/hooks/UpdateAnalyticsProps/useUpdateAnalyticsProps.js +3 -2
  114. package/dist/hooks/utils.d.cts +1 -1
  115. package/dist/hooks/utils.d.ts +1 -1
  116. package/dist/services/amplitudeService/amplitudeService.cjs +17 -57
  117. package/dist/services/amplitudeService/amplitudeService.d.cts +4 -47
  118. package/dist/services/amplitudeService/amplitudeService.d.ts +4 -47
  119. package/dist/services/amplitudeService/amplitudeService.js +14 -52
  120. package/dist/services/amplitudeService/eventNames.cjs +59 -0
  121. package/dist/services/amplitudeService/eventNames.d.cts +54 -0
  122. package/dist/services/amplitudeService/eventNames.d.ts +54 -0
  123. package/dist/services/amplitudeService/eventNames.js +57 -0
  124. package/dist/services/amplitudeService/index.cjs +3 -2
  125. package/dist/services/amplitudeService/index.d.cts +2 -1
  126. package/dist/services/amplitudeService/index.d.ts +2 -1
  127. package/dist/services/amplitudeService/index.js +2 -1
  128. package/dist/services/ga4ProjectionService/ga4EventSchema.cjs +108 -0
  129. package/dist/services/ga4ProjectionService/ga4EventSchema.js +108 -0
  130. package/dist/services/ga4ProjectionService/ga4ProjectionService.cjs +71 -0
  131. package/dist/services/ga4ProjectionService/ga4ProjectionService.js +71 -0
  132. package/dist/types/customerService.cjs +2 -1
  133. package/dist/types/customerService.d.cts +2 -1
  134. package/dist/types/customerService.d.ts +2 -1
  135. package/dist/types/customerService.js +2 -1
  136. package/package.json +1 -6
  137. package/src/application/commerce-api.ts +0 -29
  138. package/src/application/utils/analyticsUtils.ts +1 -1
  139. package/src/atoms/chat/chatState.ts +1 -1
  140. package/src/atoms/chat/replies.ts +1 -1
  141. package/src/contexts/graphqlContext/mockV3Config.ts +3 -0
  142. package/src/contexts/salesAgentContext/salesAgentService.ts +5 -2
  143. package/src/contexts/typesV3.ts +10 -0
  144. package/src/contexts/userIdentityContext/__tests__/userIdentityContext.test.tsx +1 -66
  145. package/src/contexts/userIdentityContext/userIdentityContext.tsx +0 -47
  146. package/src/hooks/AmplitudeOperations/useAmplitudeOperations.ts +2 -4
  147. package/src/hooks/ChatToggle/useChatToggle.ts +2 -4
  148. package/src/hooks/Search/useSearch.tsx +2 -4
  149. package/src/hooks/Search/useSearchInput.ts +1 -1
  150. package/src/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.ts +2 -4
  151. package/src/hooks/UpdateAnalyticsProps/useUpdateAnalyticsProps.ts +2 -4
  152. package/src/services/amplitudeService/amplitudeService.ts +14 -50
  153. package/src/services/amplitudeService/eventNames.ts +52 -0
  154. package/src/services/ga4ProjectionService/__tests__/ga4ProjectionService.test.ts +334 -0
  155. package/src/services/ga4ProjectionService/ga4EventSchema.ts +143 -0
  156. package/src/services/ga4ProjectionService/ga4ProjectionService.ts +137 -0
  157. package/src/types/customerService.ts +1 -0
  158. package/dist/hooks/IdentifyUser/index.cjs +0 -3
  159. package/dist/hooks/IdentifyUser/index.d.cts +0 -2
  160. package/dist/hooks/IdentifyUser/index.d.ts +0 -2
  161. package/dist/hooks/IdentifyUser/index.js +0 -3
  162. package/dist/hooks/IdentifyUser/useIdentifyUser.cjs +0 -35
  163. package/dist/hooks/IdentifyUser/useIdentifyUser.d.cts +0 -10
  164. package/dist/hooks/IdentifyUser/useIdentifyUser.d.ts +0 -10
  165. package/dist/hooks/IdentifyUser/useIdentifyUser.js +0 -34
  166. package/src/hooks/IdentifyUser/index.ts +0 -1
  167. package/src/hooks/IdentifyUser/useIdentifyUser.ts +0 -29
@@ -201,6 +201,15 @@ export interface AutoPopupConfig {
201
201
  triggers: AutoPopupTrigger[];
202
202
  }
203
203
 
204
+ type PartialViewConfig = {
205
+ /**
206
+ * When true, only full-screen mode is supported (no partial/draggable middle state).
207
+ * Useful when partial view causes usability issues on mobile.
208
+ * Default: false (undefined and false = partial view enabled).
209
+ */
210
+ disabled?: boolean;
211
+ };
212
+
204
213
  type FloatingChatConfig = {
205
214
  headerBackgroundColor?: string;
206
215
  headerMode: Mode;
@@ -214,6 +223,7 @@ type FloatingChatConfig = {
214
223
  welcomeMessageText: string;
215
224
  chatFooterTextFieldPlaceholderText: string;
216
225
  autoPopupConfig?: AutoPopupConfig;
226
+ partialViewConfig?: PartialViewConfig;
217
227
  };
218
228
 
219
229
  type CustomerServiceIntegration = {
@@ -1,10 +1,9 @@
1
1
  import React from 'react';
2
- import { act, render, screen, waitFor } from '@testing-library/react';
2
+ import { render, screen, waitFor } from '@testing-library/react';
3
3
  import { Provider, useStore } from 'jotai';
4
4
  import { userIdAtom } from 'src/atoms/app';
5
5
  import { LocalStorageProvider } from 'src/contexts/localStorageContext';
6
6
  import Logger from 'src/application/logging/logger';
7
- import CommerceApiClient from 'src/application/commerce-api';
8
7
  import { UserIdentityService } from 'src/services/userIdentityService';
9
8
  import { UserIdentityProvider, useUserIdentity } from '../userIdentityContext';
10
9
 
@@ -13,13 +12,6 @@ vi.spyOn(Logger, 'logInfo').mockImplementation(() => {});
13
12
  vi.spyOn(Logger, 'logWarn').mockImplementation(() => {});
14
13
  vi.spyOn(Logger, 'logError').mockImplementation(() => {});
15
14
 
16
- // Mock CommerceApiClient
17
- vi.mock('src/application/commerce-api', () => ({
18
- default: {
19
- identifyUser: vi.fn().mockResolvedValue(undefined),
20
- },
21
- }));
22
-
23
15
  // Mock uuid to have predictable values in tests
24
16
  vi.mock('uuid', () => ({
25
17
  v4: vi.fn(() => 'test-uuid-12345'),
@@ -97,31 +89,6 @@ const AtomReaderComponent: React.FC = () => {
97
89
  return <div data-testid="atom-reader">{userId}</div>;
98
90
  };
99
91
 
100
- // Component that uses the hook and triggers identifyUser
101
- const IdentifyUserComponent: React.FC = () => {
102
- const context = useUserIdentity();
103
- const [identifying, setIdentifying] = React.useState(false);
104
-
105
- const handleIdentify = async () => {
106
- setIdentifying(true);
107
- await context.identifyUser();
108
- setIdentifying(false);
109
- };
110
-
111
- return (
112
- <div>
113
- <button
114
- type="button"
115
- data-testid="identify-button"
116
- onClick={handleIdentify}
117
- >
118
- Identify
119
- </button>
120
- {identifying && <div data-testid="identifying">Identifying...</div>}
121
- </div>
122
- );
123
- };
124
-
125
92
  describe('UserIdentityProvider', () => {
126
93
  beforeEach(() => {
127
94
  vi.clearAllMocks();
@@ -334,36 +301,4 @@ describe('UserIdentityProvider', () => {
334
301
  });
335
302
  });
336
303
  });
337
-
338
- describe('identifyUser', () => {
339
- it('should call CommerceApiClient.identifyUser with correct parameters', async () => {
340
- const identifySpy = vi.spyOn(CommerceApiClient, 'identifyUser');
341
-
342
- renderWithProviders(<IdentifyUserComponent />);
343
-
344
- await waitFor(() => {
345
- expect(screen.getByTestId('identify-button')).toBeInTheDocument();
346
- });
347
-
348
- await act(async () => {
349
- screen.getByTestId('identify-button').click();
350
- });
351
-
352
- await waitFor(
353
- () => {
354
- expect(identifySpy).toHaveBeenCalled();
355
- const callArgs = identifySpy.mock.calls[0];
356
- expect(callArgs[0]).toContain('spiffy-user-id-'); // spiffyUserId
357
- expect(callArgs[1]).toBe('UNKNOWN_CDP_USER_ID'); // merchantUserId (cdpUserId)
358
- // userAgentDetails - in test environment, some values may be undefined
359
- expect(callArgs[2]).toBeDefined();
360
- expect(typeof callArgs[2]).toBe('object');
361
- // Verify it has the expected structure (values may be undefined in test env)
362
- expect(callArgs[2]).toHaveProperty('os');
363
- expect(callArgs[2]).toHaveProperty('browser');
364
- },
365
- { timeout: 3000 },
366
- );
367
- });
368
- });
369
304
  });
@@ -7,34 +7,13 @@ import React, {
7
7
  useMemo,
8
8
  useState,
9
9
  } from 'react';
10
- import UAParser from 'ua-parser-js';
11
10
  import Logger from 'src/application/logging/logger';
12
- import CommerceApiClient from 'src/application/commerce-api';
13
- import { ClientDetails } from 'src/application/models/clientDetails';
14
11
  import { useLocalStorage } from 'src/contexts/localStorageContext';
15
12
  import { useSetAtom } from 'jotai';
16
13
  import { userIdAtom } from 'src/atoms/app';
17
14
  import { UserIdentityService } from 'src/services/userIdentityService';
18
15
 
19
- // Helper function from the original service
20
- const getUserAgentDetails = (): ClientDetails => {
21
- const uaParser = new UAParser();
22
- const result = uaParser.getResult();
23
-
24
- return {
25
- os: result?.os?.name,
26
- osVersion: result?.os?.version,
27
- deviceBrand: result?.device?.vendor,
28
- deviceManufacturer: result?.device?.vendor,
29
- deviceModel: result?.device?.model,
30
- browser: result?.browser?.name,
31
- browserVersion: result?.browser?.version,
32
- userAgent: result?.ua,
33
- };
34
- };
35
-
36
16
  export interface UserIdentityContextType {
37
- identifyUser: () => Promise<void>;
38
17
  getUserIdOrDefault: () => Promise<string>;
39
18
  getUserIdOverrideFromLocalStorage: () => string | undefined;
40
19
  setUserIdOverrideInLocalStorage: (userId: string) => string;
@@ -113,33 +92,8 @@ export const UserIdentityProvider: React.FC<UserIdentityProviderProps> = ({
113
92
  }
114
93
  }, [getUserIdOverrideFromLocalStorage]);
115
94
 
116
- const identifyUser = useCallback(async (): Promise<void> => {
117
- if (!isReady) {
118
- Logger.logWarn('[UserIdentityContext] Context not ready, skipping identifyUser', undefined);
119
- return;
120
- }
121
-
122
- try {
123
- // Temporarily commented out until WindowDataLayerService is resolved
124
- // const cdpUserId = WindowDataLayerService.getGoogleAnalyticsClientId();
125
- const cdpUserId = 'UNKNOWN_CDP_USER_ID'; // Placeholder
126
- const userId = await getUserIdOrDefault();
127
- const userAgentDetails = getUserAgentDetails();
128
-
129
- if (!cdpUserId) {
130
- Logger.logWarn('[spiffy-ai] No GA Client ID found, skipping identifyUser', undefined);
131
- return;
132
- }
133
-
134
- await CommerceApiClient.identifyUser(userId, cdpUserId, userAgentDetails);
135
- } catch (error) {
136
- Logger.logError('[spiffy-ai] Error identifying user', error);
137
- }
138
- }, [isReady, getUserIdOrDefault]);
139
-
140
95
  const value = useMemo(
141
96
  () => ({
142
- identifyUser,
143
97
  getUserIdOrDefault,
144
98
  getUserIdOverrideFromLocalStorage,
145
99
  setUserIdOverrideInLocalStorage,
@@ -147,7 +101,6 @@ export const UserIdentityProvider: React.FC<UserIdentityProviderProps> = ({
147
101
  isReady,
148
102
  }),
149
103
  [
150
- identifyUser,
151
104
  getUserIdOrDefault,
152
105
  getUserIdOverrideFromLocalStorage,
153
106
  setUserIdOverrideInLocalStorage,
@@ -1,8 +1,6 @@
1
1
  import { useCallback, useState } from 'react';
2
- import {
3
- SpiffyMetricsEventName,
4
- useAmplitude,
5
- } from 'src/contexts/amplitudeContext/amplitudeContext';
2
+ import { useAmplitude } from 'src/contexts/amplitudeContext/amplitudeContext';
3
+ import { SpiffyMetricsEventName } from 'src/services/amplitudeService/amplitudeService';
6
4
 
7
5
  export const useAmplitudeTracking = () => {
8
6
  const { trackEvent, isReady } = useAmplitude();
@@ -1,10 +1,8 @@
1
1
  import { useAtomValue, useSetAtom } from 'jotai';
2
2
  import { ChatElementDisplayLocationV3 } from 'src/application/models';
3
3
  import { chatAtom, chatOnToggleAtom } from 'src/atoms/chat';
4
- import {
5
- SpiffyMetricsEventName,
6
- useAmplitude,
7
- } from 'src/contexts/amplitudeContext/amplitudeContext';
4
+ import { useAmplitude } from 'src/contexts/amplitudeContext/amplitudeContext';
5
+ import { SpiffyMetricsEventName } from 'src/services/amplitudeService/amplitudeService';
8
6
 
9
7
  export const useChatToggle = () => {
10
8
  const onToggle = useSetAtom(chatOnToggleAtom);
@@ -18,10 +18,8 @@ import {
18
18
  import { isFilterOpenAtom } from 'src/atoms/globalSearch/globalSearch';
19
19
  import { formatFilterDisplayName } from 'src/atoms/search/utils';
20
20
  import { ProductSorting } from 'src/atoms/search/types';
21
- import {
22
- SpiffyMetricsEventName,
23
- useAmplitude,
24
- } from 'src/contexts/amplitudeContext/amplitudeContext';
21
+ import { useAmplitude } from 'src/contexts/amplitudeContext/amplitudeContext';
22
+ import { SpiffyMetricsEventName } from 'src/services/amplitudeService/amplitudeService';
25
23
  import { SpiffyWidgets } from 'src/application/models/spiffyWidgets';
26
24
  import { ProductCardConfig } from 'src/contexts/types';
27
25
  import { SearchResult } from 'src/application/models/api/search';
@@ -4,7 +4,7 @@ import Fuse from 'fuse.js';
4
4
 
5
5
  import { autocompleteStateAtom } from 'src/atoms/globalSearch';
6
6
  import { amplitudeTrackEventAtom } from 'src/atoms/amplitude/amplitudeTrackEventAtom';
7
- import { SpiffyMetricsEventName } from 'src/contexts/amplitudeContext';
7
+ import { SpiffyMetricsEventName } from 'src/services/amplitudeService/amplitudeService';
8
8
  import { SpiffyWidgets } from 'src/application/models/spiffyWidgets';
9
9
 
10
10
  export interface UseSearchInputProps {
@@ -1,10 +1,8 @@
1
1
  import { RefObject, useEffect, useRef } from 'react';
2
2
  import { SpiffyWidgets } from 'src/application/models/spiffyWidgets';
3
3
  import { useIntersection } from 'src/hooks/Intersection/useIntersection';
4
- import {
5
- SpiffyMetricsEventName,
6
- useAmplitude,
7
- } from 'src/contexts/amplitudeContext/amplitudeContext';
4
+ import { useAmplitude } from 'src/contexts/amplitudeContext/amplitudeContext';
5
+ import { SpiffyMetricsEventName } from 'src/services/amplitudeService/amplitudeService';
8
6
 
9
7
  /**
10
8
  * Tracks a component and logs an event to Amplitude when the component is visible.
@@ -1,9 +1,7 @@
1
1
  import { useAtomValue } from 'jotai';
2
2
  import { useEffect, useRef } from 'react';
3
- import {
4
- SpiffyMetricsEventName,
5
- useAmplitude,
6
- } from 'src/contexts/amplitudeContext/amplitudeContext';
3
+ import { useAmplitude } from 'src/contexts/amplitudeContext/amplitudeContext';
4
+ import { SpiffyMetricsEventName } from 'src/services/amplitudeService/amplitudeService';
7
5
  import { hasParsedVariantInfoAtom, variantInfoAtom } from 'src/atoms/app/variant';
8
6
 
9
7
  /**
@@ -11,52 +11,11 @@ import type {
11
11
  import { FeatureFlagService } from 'src/contexts/featureFlagServiceContext/featureFlagServiceContext';
12
12
  import { WidgetTypeV3 } from 'src/contexts/typesV3';
13
13
  import { ChatElementDisplayLocationV3 } from 'src/application/models/chatElementDisplayLocationV3';
14
+ import { projectToGA4 } from '../ga4ProjectionService/ga4ProjectionService';
15
+ import { EnviveMetricsEventName, SpiffyMetricsEventName } from './eventNames';
14
16
 
15
- export enum SpiffyMetricsEventName {
16
- BundleLoaded = 'Bundle Loaded',
17
- EnvironmentInitialized = 'Environment Initialized',
18
- ChatLiveAgentBtnClick = 'Chat Live Agent Btn Click',
19
- ChatFloatingButtonVisible = 'Chat Floating Button Visible',
20
- ChatComponentVisible = 'Chat Component Visible',
21
- ChatComponentExpanded = 'Chat Component Expanded',
22
- ChatComponentCollapsed = 'Chat Component Collapsed',
23
- ChatUserMessageInput = 'Chat User Message Input',
24
- ChatSuggestionClicked = 'Chat Suggestion Clicked',
25
- ChatAssistantResponse = 'Chat Assistant Response',
26
- ProductCardClicked = 'Product Card Clicked',
27
- ProductReviewCardClicked = 'Product Review Card Clicked',
28
- AddToCartClicked = 'Add To Cart Clicked',
29
- PromptCardClicked = 'Prompt Card Clicked',
30
- SupportedEvent = 'Supported Event',
31
- SearchBackToResponseClicked = 'Search Back to Response Clicked',
32
- PerformanceMetrics = 'Performance Metrics',
33
- SearchBarClicked = 'Search Bar Clicked',
34
- OrderLookupStarted = 'Order Lookup Started',
35
- OrderLookupFormSubmitted = 'Order Lookup Form Submitted',
36
- SearchComponentVisible = 'Search Component Visible',
37
- SearchZeroStateSuggestionClicked = 'Search Zero State Suggestion Clicked', // This is the scrolling list of suggestion buttons in global search
38
- SearchInputStarted = 'Search Input Started',
39
- SearchQuerySubmitted = 'Search Query Submitted',
40
- // SearchAutocompleteViewed = 'Search Autocomplete Viewed', // TODO: add this when autocomplete is added
41
- // SearchAutocompleteClicked = 'Search Autocomplete Clicked', // TODO: add this when autocomplete is added
42
- SearchResultsViewed = 'Search Results Viewed',
43
- SearchTimeToFirstClick = 'Search Time to First Click',
44
- SearchZeroResultsRate = 'Search Zero Results Rate',
45
- SearchFilterClicked = 'Search Filter Clicked',
46
- SearchSortClicked = 'Search Sort Clicked',
47
- }
48
-
49
- export enum EnviveMetricsEventName {
50
- WidgetRendered = 'Widget Rendered',
51
- WidgetInteraction = 'Widget Interaction',
52
- ChatRequest = 'Chat Request',
53
- ChatResponse = 'Chat Response',
54
- EnviveInitialized = 'Envive Initialized',
55
- PageViewed = 'Page Viewed', // Will this be useful?
56
- WidgetTextRequest = 'Widget Text Request',
57
- WidgetTextResponse = 'Widget Text Response',
58
- WidgetTextClicked = 'Widget Text Clicked',
59
- }
17
+ // Re-export event names for convenience
18
+ export { EnviveMetricsEventName, SpiffyMetricsEventName };
60
19
 
61
20
  export interface TrackEventParams {
62
21
  eventName: SpiffyMetricsEventName | EnviveMetricsEventName;
@@ -142,7 +101,7 @@ export class AmplitudeService {
142
101
  'environment.envive_enabled': this.config.enabledFeatures?.envive,
143
102
  };
144
103
 
145
- const orgLevelAmplitudeTrackingProps = AmplitudeService.isEnviveEvent(eventName)
104
+ const orgLevelAmplitudeTrackingProps = AmplitudeService.isV3EnviveEvent(eventName)
146
105
  ? {
147
106
  ...this.config.featureFlagService.getFullFlagValues(),
148
107
  ...experimentProps,
@@ -375,12 +334,12 @@ export class AmplitudeService {
375
334
  return eventProps ?? {};
376
335
  }
377
336
 
378
- static isEnviveEvent(eventName: SpiffyMetricsEventName | EnviveMetricsEventName): boolean {
337
+ static isV3EnviveEvent(eventName: SpiffyMetricsEventName | EnviveMetricsEventName): boolean {
379
338
  return Object.values(EnviveMetricsEventName).includes(eventName as EnviveMetricsEventName);
380
339
  }
381
340
 
382
341
  static decorateEventName(eventName: SpiffyMetricsEventName | EnviveMetricsEventName): string {
383
- if (AmplitudeService.isEnviveEvent(eventName)) {
342
+ if (AmplitudeService.isV3EnviveEvent(eventName)) {
384
343
  return `[Envive] ${eventName}`;
385
344
  }
386
345
  return `[Spiffy] ${eventName}`;
@@ -438,8 +397,13 @@ export class AmplitudeService {
438
397
  },
439
398
  );
440
399
 
441
- if (alsoSendToGoogleAnalytics && this.config.orgGaConfig) {
442
- // TODO: Add in windowDataLayerService or context alternative and hook it up here
400
+ if (AmplitudeService.isV3EnviveEvent(eventName) && this.config.orgGaConfig) {
401
+ const mergedPropsForGA4 = {
402
+ ...this.getDefaultTrackingProps(eventName),
403
+ ...mappedEventProps,
404
+ };
405
+ projectToGA4(eventName as EnviveMetricsEventName, mergedPropsForGA4);
406
+ } else if (alsoSendToGoogleAnalytics && this.config.orgGaConfig) {
443
407
  Logger.logDebug('[spiffy-ai] GA tracking', decoratedEventName);
444
408
  if (typeof window !== 'undefined' && window.dataLayer) {
445
409
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Event name enums for Amplitude tracking.
3
+ *
4
+ * NOTE: This file exists separately to avoid circular dependency issues.
5
+ * The amplitudeService imports from ga4ProjectionService, which needs these enums.
6
+ * By keeping the enums in a separate file, ga4ProjectionService can import them
7
+ * without creating a circular dependency with amplitudeService.
8
+ */
9
+
10
+ export enum SpiffyMetricsEventName {
11
+ BundleLoaded = 'Bundle Loaded',
12
+ EnvironmentInitialized = 'Environment Initialized',
13
+ ChatLiveAgentBtnClick = 'Chat Live Agent Btn Click',
14
+ ChatFloatingButtonVisible = 'Chat Floating Button Visible',
15
+ ChatComponentVisible = 'Chat Component Visible',
16
+ ChatComponentExpanded = 'Chat Component Expanded',
17
+ ChatComponentCollapsed = 'Chat Component Collapsed',
18
+ ChatUserMessageInput = 'Chat User Message Input',
19
+ ChatSuggestionClicked = 'Chat Suggestion Clicked',
20
+ ChatAssistantResponse = 'Chat Assistant Response',
21
+ ProductCardClicked = 'Product Card Clicked',
22
+ ProductReviewCardClicked = 'Product Review Card Clicked',
23
+ AddToCartClicked = 'Add To Cart Clicked',
24
+ PromptCardClicked = 'Prompt Card Clicked',
25
+ SupportedEvent = 'Supported Event',
26
+ SearchBackToResponseClicked = 'Search Back to Response Clicked',
27
+ PerformanceMetrics = 'Performance Metrics',
28
+ SearchBarClicked = 'Search Bar Clicked',
29
+ OrderLookupStarted = 'Order Lookup Started',
30
+ OrderLookupFormSubmitted = 'Order Lookup Form Submitted',
31
+ SearchComponentVisible = 'Search Component Visible',
32
+ SearchZeroStateSuggestionClicked = 'Search Zero State Suggestion Clicked',
33
+ SearchInputStarted = 'Search Input Started',
34
+ SearchQuerySubmitted = 'Search Query Submitted',
35
+ SearchResultsViewed = 'Search Results Viewed',
36
+ SearchTimeToFirstClick = 'Search Time to First Click',
37
+ SearchZeroResultsRate = 'Search Zero Results Rate',
38
+ SearchFilterClicked = 'Search Filter Clicked',
39
+ SearchSortClicked = 'Search Sort Clicked',
40
+ }
41
+
42
+ export enum EnviveMetricsEventName {
43
+ WidgetRendered = 'Widget Rendered',
44
+ WidgetInteraction = 'Widget Interaction',
45
+ ChatRequest = 'Chat Request',
46
+ ChatResponse = 'Chat Response',
47
+ EnviveInitialized = 'Envive Initialized',
48
+ PageViewed = 'Page Viewed',
49
+ WidgetTextRequest = 'Widget Text Request',
50
+ WidgetTextResponse = 'Widget Text Response',
51
+ WidgetTextClicked = 'Widget Text Clicked',
52
+ }