From b5c12916d4e1f142a89071adfb0ce4018488a274 Mon Sep 17 00:00:00 2001 From: namdaeun Date: Mon, 20 Jan 2025 18:28:11 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20react-ga4=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + yarn.lock | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c2be9ad3..b1d4f85b 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "quill-divider": "^0.2.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-ga4": "^2.1.0", "react-helmet-async": "^2.0.5", "react-quill": "^2.0.0", "react-router-dom": "^6.26.1", diff --git a/yarn.lock b/yarn.lock index 04adeea8..b88c4493 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6091,6 +6091,11 @@ react-fast-compare@^3.2.2: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== +react-ga4@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-ga4/-/react-ga4-2.1.0.tgz#56601f59d95c08466ebd6edfbf8dede55c4678f9" + integrity sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ== + react-helmet-async@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-2.0.5.tgz#cfc70cd7bb32df7883a8ed55502a1513747223ec" @@ -6756,7 +6761,16 @@ string-convert@^0.2.0: resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -6830,7 +6844,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -7390,7 +7411,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -7408,6 +7429,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From adafbd5c5a80d5e6c483559825e0833f0746c6f7 Mon Sep 17 00:00:00 2001 From: namdaeun Date: Mon, 20 Jan 2025 18:55:49 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20routeChangeTracker=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 4 ++++ src/routers/routeChangeTracker.ts | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/routers/routeChangeTracker.ts diff --git a/src/App.tsx b/src/App.tsx index da1c166f..69fbd0a0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,10 +6,13 @@ import { HelmetProvider } from 'react-helmet-async'; import { RouterProvider } from 'react-router-dom'; import ResponsiveProvider from './components/commons/Responsive/ResponsiveProvider'; import Loading from './pages/loading/Loading'; +import { routeChangeTracker } from './routers/routeChangeTracker'; import router from './routers/Router'; import { MOBILE_MEDIA_QUERY } from './styles/mediaQuery'; const App = () => { + routeChangeTracker(); + const queryClient = new QueryClient({ defaultOptions: { queries: { @@ -17,6 +20,7 @@ const App = () => { }, }, }); + return ( diff --git a/src/routers/routeChangeTracker.ts b/src/routers/routeChangeTracker.ts new file mode 100644 index 00000000..fc3e02df --- /dev/null +++ b/src/routers/routeChangeTracker.ts @@ -0,0 +1,25 @@ +import { useEffect, useState } from 'react'; +import ReactGA from 'react-ga4'; +import { useLocation } from 'react-router-dom'; + +export const routeChangeTracker = () => { + const [isInitialized, setIsInitialized] = useState(false); + + const location = useLocation(); + + useEffect(() => { + if (!window.location.href.includes('localhost')) { + ReactGA.initialize(import.meta.env.VITE_GOOGLE_ANALYTICS_ID); + } + + setIsInitialized(true); + }, []); + + // location 변경시 pageView 이벤트 전송 + useEffect(() => { + if (isInitialized) { + ReactGA.set({ page: location.pathname }); + ReactGA.send('pageView'); + } + }, [isInitialized, location]); +}; From c6c6af405e27396bd07b0ebd4111577fda8c8d25 Mon Sep 17 00:00:00 2001 From: namdaeun Date: Mon, 20 Jan 2025 18:58:52 +0900 Subject: [PATCH 3/8] =?UTF-8?q?fix:=20RouterProvider=20=EB=82=B4=EB=B6=80?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=98=B8=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 8 +++----- .../{routeChangeTracker.ts => RouteTracker.tsx} | 13 ++++++++----- 2 files changed, 11 insertions(+), 10 deletions(-) rename src/routers/{routeChangeTracker.ts => RouteTracker.tsx} (77%) diff --git a/src/App.tsx b/src/App.tsx index 69fbd0a0..f907f1d7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,13 +6,12 @@ import { HelmetProvider } from 'react-helmet-async'; import { RouterProvider } from 'react-router-dom'; import ResponsiveProvider from './components/commons/Responsive/ResponsiveProvider'; import Loading from './pages/loading/Loading'; -import { routeChangeTracker } from './routers/routeChangeTracker'; + import router from './routers/Router'; +import RouteTracker from './routers/RouteTracker'; import { MOBILE_MEDIA_QUERY } from './styles/mediaQuery'; const App = () => { - routeChangeTracker(); - const queryClient = new QueryClient({ defaultOptions: { queries: { @@ -26,9 +25,9 @@ const App = () => { - {/*
*/} }> + @@ -48,7 +47,6 @@ const DesktopWrapper = styled.div` scroll-behavior: smooth; @media ${MOBILE_MEDIA_QUERY} { - /* width: 100%; */ width: 100%; max-width: 83rem; } diff --git a/src/routers/routeChangeTracker.ts b/src/routers/RouteTracker.tsx similarity index 77% rename from src/routers/routeChangeTracker.ts rename to src/routers/RouteTracker.tsx index fc3e02df..5a56566f 100644 --- a/src/routers/routeChangeTracker.ts +++ b/src/routers/RouteTracker.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import ReactGA from 'react-ga4'; import { useLocation } from 'react-router-dom'; -export const routeChangeTracker = () => { +const RouteTracker = () => { const [isInitialized, setIsInitialized] = useState(false); const location = useLocation(); @@ -10,16 +10,19 @@ export const routeChangeTracker = () => { useEffect(() => { if (!window.location.href.includes('localhost')) { ReactGA.initialize(import.meta.env.VITE_GOOGLE_ANALYTICS_ID); - } - setIsInitialized(true); + setIsInitialized(true); + } }, []); - // location 변경시 pageView 이벤트 전송 useEffect(() => { if (isInitialized) { ReactGA.set({ page: location.pathname }); - ReactGA.send('pageView'); + ReactGA.send('page'); } }, [isInitialized, location]); + + return null; }; + +export default RouteTracker; From 33e3a27f0f9e8848accd60ddbedc80931ba49cb8 Mon Sep 17 00:00:00 2001 From: namdaeun Date: Mon, 20 Jan 2025 19:01:43 +0900 Subject: [PATCH 4/8] =?UTF-8?q?fix:=20set=ED=95=A8=EC=88=98=20if=EB=AC=B8?= =?UTF-8?q?=20=EB=B0=96=EC=97=90=EC=84=9C=20=ED=98=B8=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routers/RouteTracker.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routers/RouteTracker.tsx b/src/routers/RouteTracker.tsx index 5a56566f..13cbf082 100644 --- a/src/routers/RouteTracker.tsx +++ b/src/routers/RouteTracker.tsx @@ -10,9 +10,9 @@ const RouteTracker = () => { useEffect(() => { if (!window.location.href.includes('localhost')) { ReactGA.initialize(import.meta.env.VITE_GOOGLE_ANALYTICS_ID); - - setIsInitialized(true); } + + setIsInitialized(true); }, []); useEffect(() => { From 322c4b250a53d78e386989c4aba5b2f093ae96d2 Mon Sep 17 00:00:00 2001 From: namdaeun Date: Mon, 20 Jan 2025 19:17:01 +0900 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20set=ED=95=A8=EC=88=98=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routers/RouteTracker.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routers/RouteTracker.tsx b/src/routers/RouteTracker.tsx index 13cbf082..5a56566f 100644 --- a/src/routers/RouteTracker.tsx +++ b/src/routers/RouteTracker.tsx @@ -10,9 +10,9 @@ const RouteTracker = () => { useEffect(() => { if (!window.location.href.includes('localhost')) { ReactGA.initialize(import.meta.env.VITE_GOOGLE_ANALYTICS_ID); - } - setIsInitialized(true); + setIsInitialized(true); + } }, []); useEffect(() => { From 8468ca6afce037af7ae797212e20598b83089b54 Mon Sep 17 00:00:00 2001 From: namdaeun Date: Mon, 20 Jan 2025 19:18:04 +0900 Subject: [PATCH 6/8] =?UTF-8?q?chore:=20send=20code=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routers/RouteTracker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routers/RouteTracker.tsx b/src/routers/RouteTracker.tsx index 5a56566f..61018a44 100644 --- a/src/routers/RouteTracker.tsx +++ b/src/routers/RouteTracker.tsx @@ -18,7 +18,7 @@ const RouteTracker = () => { useEffect(() => { if (isInitialized) { ReactGA.set({ page: location.pathname }); - ReactGA.send('page'); + ReactGA.send('pageview'); } }, [isInitialized, location]); From ea288c00858cefc1aae87742d0ce7fb5d3ee3583 Mon Sep 17 00:00:00 2001 From: namdaeun Date: Mon, 20 Jan 2025 20:02:14 +0900 Subject: [PATCH 7/8] =?UTF-8?q?fix:=20send=20=EB=B0=A9=EC=8B=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routers/RouteTracker.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/routers/RouteTracker.tsx b/src/routers/RouteTracker.tsx index 61018a44..98a47a59 100644 --- a/src/routers/RouteTracker.tsx +++ b/src/routers/RouteTracker.tsx @@ -17,8 +17,7 @@ const RouteTracker = () => { useEffect(() => { if (isInitialized) { - ReactGA.set({ page: location.pathname }); - ReactGA.send('pageview'); + ReactGA.send({ hitType: 'pageview', page: location.pathname }); } }, [isInitialized, location]); From 5146b5d424a50ab1f36a8a4819422afe8e28c8c4 Mon Sep 17 00:00:00 2001 From: namdaeun Date: Tue, 21 Jan 2025 17:08:09 +0900 Subject: [PATCH 8/8] =?UTF-8?q?fix:=20RouteTracker=20=ED=98=B8=EC=B6=9C=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 2 -- src/components/commons/Layout.tsx | 2 ++ src/routers/PrivateRoute.tsx | 10 +++++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index f907f1d7..2a786e25 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -8,7 +8,6 @@ import ResponsiveProvider from './components/commons/Responsive/ResponsiveProvid import Loading from './pages/loading/Loading'; import router from './routers/Router'; -import RouteTracker from './routers/RouteTracker'; import { MOBILE_MEDIA_QUERY } from './styles/mediaQuery'; const App = () => { @@ -27,7 +26,6 @@ const App = () => { }> - diff --git a/src/components/commons/Layout.tsx b/src/components/commons/Layout.tsx index b535b618..68225540 100644 --- a/src/components/commons/Layout.tsx +++ b/src/components/commons/Layout.tsx @@ -1,9 +1,11 @@ import { Outlet } from 'react-router-dom'; +import RouteTracker from '../../routers/RouteTracker'; import ScrollToTop from './ScrollToTop'; const Layout = () => { return ( <> + diff --git a/src/routers/PrivateRoute.tsx b/src/routers/PrivateRoute.tsx index 943699ba..7f7027f4 100644 --- a/src/routers/PrivateRoute.tsx +++ b/src/routers/PrivateRoute.tsx @@ -1,12 +1,20 @@ import { Navigate, Outlet, useLocation } from 'react-router-dom'; import checkAuthenticate from '../utils/checkAuthenticate'; +import RouteTracker from './RouteTracker'; const PrivateRoute = () => { const pathname = useLocation(); if (!checkAuthenticate()) { alert('로그인 후 이용이 가능합니다.'); } - return checkAuthenticate() ? : ; + return checkAuthenticate() ? ( + <> + + + + ) : ( + + ); }; export default PrivateRoute;