瀏覽代碼

Added Segment, Google Analytics, Google Optimize (#4308)

* added segment, google analytics, google optimize

* add RR location

---------

Co-authored-by: Artem <Artem Slugin>
attemka 1 年之前
父節點
當前提交
e1b3dfc5e3

+ 4 - 0
packages/atlas/atlas.config.yml

@@ -463,6 +463,10 @@ analytics:
     rootHostname: '$VITE_LIVESESSION_ROOT_HOSTNAME'
   usersnap: # Usersnap can be used to capture user feedback
     id: '$VITE_USERSNAP_ID'
+  GA: # Google Analytics
+    id: '$VITE_GA_ID'
+  segment: # Segment Analytics
+    id: '$VITE_SEGMENT_ID'
 
 legal:
   termsOfService: |

+ 3 - 1
packages/atlas/package.json

@@ -43,6 +43,7 @@
     "@livesession/sdk": "^1.1.4",
     "@loadable/component": "^5.15.2",
     "@lottiefiles/react-lottie-player": "^3.5.0",
+    "@segment/analytics-next": "^1.53.0",
     "@sentry/react": "^7.53.1",
     "@talismn/connect-wallets": "^1.2.1",
     "@tippyjs/react": "^4.2.6",
@@ -137,12 +138,13 @@
     "js-yaml": "^4.1.0",
     "madge": "^5.0.1",
     "postcss-syntax": "^0.36.2",
+    "react-ga": "^3.3.1",
     "react-hooks-testing-library": "^0.6.0",
     "rimraf": "^3.0.2",
     "rollup-plugin-visualizer": "^5.8.3",
     "storybook": "7.0.7",
     "style-dictionary": "^3.7.1",
-    "vite": "^4.0.1",
+    "vite": "^4.3.9",
     "vite-plugin-checker": "^0.5.2",
     "vitest": "^0.25.7"
   },

+ 24 - 0
packages/atlas/src/AnalyticsManager.tsx

@@ -1,5 +1,7 @@
 import ls from '@livesession/sdk'
 import { FC, useCallback, useEffect } from 'react'
+import ReactGA from 'react-ga'
+import { useLocation } from 'react-router-dom'
 
 import { atlasConfig } from '@/config'
 import { BUILD_ENV } from '@/config/env'
@@ -8,6 +10,7 @@ import { usePersonalDataStore } from '@/providers/personalData'
 export const AnalyticsManager: FC = () => {
   const cookiesAccepted = usePersonalDataStore((state) => state.cookiesAccepted)
   const analyticsEnabled = BUILD_ENV === 'production' && cookiesAccepted
+  const location = useLocation()
 
   const initUsersnap = useCallback(() => {
     if (!atlasConfig.analytics.usersnap?.id) return
@@ -36,6 +39,12 @@ export const AnalyticsManager: FC = () => {
     ls.newPageView()
   }, [])
 
+  const initGA = useCallback(() => {
+    if (!atlasConfig.analytics.GA?.id) return
+
+    ReactGA.initialize(atlasConfig.analytics.GA.id)
+  }, [])
+
   // initialize livesession
   useEffect(() => {
     if (!analyticsEnabled) return
@@ -50,5 +59,20 @@ export const AnalyticsManager: FC = () => {
     initUsersnap()
   }, [analyticsEnabled, initUsersnap])
 
+  //initialize Google Analytics
+  useEffect(() => {
+    if (!analyticsEnabled) return
+
+    initGA()
+  }, [analyticsEnabled, initGA])
+
+  //track pageview in GA
+  useEffect(() => {
+    if (!analyticsEnabled || !atlasConfig.analytics.GA?.id) {
+      return
+    }
+    ReactGA.pageview(location.pathname)
+  }, [location.pathname, analyticsEnabled])
+
   return null
 }

+ 11 - 8
packages/atlas/src/CommonProviders.tsx

@@ -10,6 +10,7 @@ import { AdminModal } from '@/components/_overlays/AdminModal'
 import { OperatorsContextProvider } from '@/providers/assets/assets.provider'
 import { ConfirmationModalProvider } from '@/providers/confirmationModal'
 import { OverlayManagerProvider } from '@/providers/overlayManager'
+import { SegmentAnalyticsProvider } from '@/providers/segmentAnalytics/segment.provider'
 import { UserProvider } from '@/providers/user/user.provider'
 import { GlobalStyles } from '@/styles'
 
@@ -34,14 +35,16 @@ export const CommonProviders: FC<PropsWithChildren> = ({ children }) => {
         <QueryClientProvider client={queryClient}>
           <UserProvider>
             <OverlayManagerProvider>
-              <ConfirmationModalProvider>
-                <BrowserRouter>
-                  <AdminModal />
-                  <MaintenanceWrapper>
-                    <OperatorsContextProvider>{children}</OperatorsContextProvider>
-                  </MaintenanceWrapper>
-                </BrowserRouter>
-              </ConfirmationModalProvider>
+              <SegmentAnalyticsProvider>
+                <ConfirmationModalProvider>
+                  <BrowserRouter>
+                    <AdminModal />
+                    <MaintenanceWrapper>
+                      <OperatorsContextProvider>{children}</OperatorsContextProvider>
+                    </MaintenanceWrapper>
+                  </BrowserRouter>
+                </ConfirmationModalProvider>
+              </SegmentAnalyticsProvider>
             </OverlayManagerProvider>
           </UserProvider>
         </QueryClientProvider>

+ 10 - 0
packages/atlas/src/config/configSchema.ts

@@ -146,6 +146,16 @@ export const configSchema = z.object({
         id: z.string().nullable(),
       })
       .nullable(),
+    GA: z
+      .object({
+        id: z.string().nullable(),
+      })
+      .nullable(),
+    segment: z
+      .object({
+        id: z.string().nullable(),
+      })
+      .nullable(),
   }),
   legal: z.object({
     termsOfService: z.string(),

+ 20 - 0
packages/atlas/src/hooks/useSegmentAnalytics.ts

@@ -0,0 +1,20 @@
+import { useCallback } from 'react'
+
+import useSegmentAnalyticsContext from '@/providers/segmentAnalytics/useSegmentAnalyticsContext'
+
+const useAnalytics = () => {
+  const { analytics } = useSegmentAnalyticsContext()
+
+  const pageViewed = useCallback(
+    (name: string, category = 'App') => {
+      analytics.page(category, name)
+    },
+    [analytics]
+  )
+
+  return {
+    pageViewed,
+  }
+}
+
+export default useAnalytics

+ 1 - 0
packages/atlas/src/index.html

@@ -20,6 +20,7 @@
       href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@600;700&family=Roboto:wght@400&family=Inter:wght@400;500;600;700&display=swap"
       rel="stylesheet"
     />
+    <script src="https://www.googleoptimize.com/optimize.js?id=%VITE_OPTIMIZE_ID%"></script>
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>

+ 31 - 0
packages/atlas/src/providers/segmentAnalytics/segment.provider.tsx

@@ -0,0 +1,31 @@
+import { AnalyticsBrowser } from '@segment/analytics-next'
+import { FC, ReactNode, createContext, useMemo } from 'react'
+
+import { atlasConfig } from '@/config'
+import { BUILD_ENV } from '@/config/env'
+import { usePersonalDataStore } from '@/providers/personalData'
+
+import { AnalyticsContextProps } from './segment.types'
+
+interface AnalyticsProviderProps {
+  children: ReactNode
+}
+
+const defaultAnalyticsContext = {
+  analytics: new AnalyticsBrowser(),
+}
+
+export const SegmentAnalyticsContext = createContext<AnalyticsContextProps>(defaultAnalyticsContext)
+
+export const SegmentAnalyticsProvider: FC<AnalyticsProviderProps> = ({ children }) => {
+  const cookiesAccepted = usePersonalDataStore((state) => state.cookiesAccepted)
+  const analyticsEnabled = BUILD_ENV === 'production' && cookiesAccepted
+  const writeKey = (analyticsEnabled && atlasConfig.analytics.segment?.id) || ''
+
+  const segmentAnalytics: AnalyticsContextProps = useMemo(
+    () => ({ analytics: AnalyticsBrowser.load({ writeKey }) }),
+    [writeKey]
+  )
+
+  return <SegmentAnalyticsContext.Provider value={segmentAnalytics}>{children}</SegmentAnalyticsContext.Provider>
+}

+ 5 - 0
packages/atlas/src/providers/segmentAnalytics/segment.types.ts

@@ -0,0 +1,5 @@
+import { AnalyticsBrowser } from '@segment/analytics-next'
+
+export interface AnalyticsContextProps {
+  analytics: AnalyticsBrowser
+}

+ 7 - 0
packages/atlas/src/providers/segmentAnalytics/useSegmentAnalyticsContext.ts

@@ -0,0 +1,7 @@
+import { useContext } from 'react'
+
+import { SegmentAnalyticsContext } from './segment.provider'
+
+const useSegmentAnalyticsContext = () => useContext(SegmentAnalyticsContext)
+
+export default useSegmentAnalyticsContext

File diff suppressed because it is too large
+ 1537 - 99
yarn.lock


Some files were not shown because too many files changed in this diff