diff --git a/index.html b/index.html index 2f390167..bf9f9275 100644 --- a/index.html +++ b/index.html @@ -29,7 +29,7 @@ > diff --git a/src/components/common/Layout/DefaultLayout.tsx b/src/components/common/Layout/DefaultLayout.tsx index c57ecae8..7d4aaed3 100644 --- a/src/components/common/Layout/DefaultLayout.tsx +++ b/src/components/common/Layout/DefaultLayout.tsx @@ -1,7 +1,10 @@ import { Outlet } from 'react-router-dom'; import Navigation from '@/components/common/Navigation/Navigation'; +import usePageViewTracking from '@/hooks/usePageViewTracking'; export default function DefaultLayout() { + usePageViewTracking(); + return (
diff --git a/src/components/common/Layout/SubLayout.tsx b/src/components/common/Layout/SubLayout.tsx index a18d3837..c8fba9a4 100644 --- a/src/components/common/Layout/SubLayout.tsx +++ b/src/components/common/Layout/SubLayout.tsx @@ -1,6 +1,9 @@ import { Outlet } from 'react-router-dom'; +import usePageViewTracking from '@/hooks/usePageViewTracking'; export default function SubLayout() { + usePageViewTracking(); + return (
diff --git a/src/components/poll-detail/Button/PollButton.tsx b/src/components/poll-detail/Button/PollButton.tsx index 3b0459e0..b8d3d5a9 100644 --- a/src/components/poll-detail/Button/PollButton.tsx +++ b/src/components/poll-detail/Button/PollButton.tsx @@ -1,4 +1,5 @@ import { useQueryClient } from '@tanstack/react-query'; +import ReactGA from 'react-ga4'; import usePost from '@/api/usePost'; import { Button } from '@/components/common/Button/Button'; import useToast from '@/components/common/Toast/hooks'; @@ -16,6 +17,10 @@ export default function PollButton({ postId, checkedItems }: PollButtonProps) { const { mutate: vote, isPending } = usePost({ onSuccess: () => { + ReactGA.event('poll_voted', { + post_id: postId, + }); + queryClient.invalidateQueries({ queryKey: ['post', String(postId)] }); queryClient.invalidateQueries({ queryKey: ['postResult', String(postId)], @@ -26,7 +31,6 @@ export default function PollButton({ postId, checkedItems }: PollButtonProps) { description: '투표가 성공적으로 완료되었어요.', }); - // voteMode 종료 setVoteMode(false); }, }); diff --git a/src/hooks/usePageViewTracking.ts b/src/hooks/usePageViewTracking.ts new file mode 100644 index 00000000..23dc32fc --- /dev/null +++ b/src/hooks/usePageViewTracking.ts @@ -0,0 +1,14 @@ +import { useEffect } from 'react'; +import ReactGA from 'react-ga4'; +import { useLocation } from 'react-router-dom'; + +export default function usePageViewTracking() { + const location = useLocation(); + + useEffect(() => { + ReactGA.send({ + hitType: 'pageview', + page: location.pathname + location.search, + }); + }, [location]); +} diff --git a/src/pages/OnBoarding/OnBoardingPage.tsx b/src/pages/OnBoarding/OnBoardingPage.tsx index bc18b0b3..54ebebd6 100644 --- a/src/pages/OnBoarding/OnBoardingPage.tsx +++ b/src/pages/OnBoarding/OnBoardingPage.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from 'react'; +import ReactGA from 'react-ga4'; import { useNavigate } from 'react-router-dom'; import useGetMyInfo from '@/api/useGetMyInfo'; import onboardingImage from '@/assets/images/onboarding/onboarding.png'; @@ -22,6 +23,12 @@ export default function OnBoardingPage() { }, 2500); }, []); + useEffect(() => { + if (!showSplash) { + ReactGA.event('onboarding_viewed'); + } + }, [showSplash]); + if (showSplash) { return (
diff --git a/src/pages/PollDetail/PollResultPage.tsx b/src/pages/PollDetail/PollResultPage.tsx index 34d64a42..9cb210ac 100644 --- a/src/pages/PollDetail/PollResultPage.tsx +++ b/src/pages/PollDetail/PollResultPage.tsx @@ -1,3 +1,5 @@ +import { useEffect } from 'react'; +import ReactGA from 'react-ga4'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { useGetNotificationPresent } from '@/api/useGetNotificationPresent'; import { useGetPost } from '@/api/useGetPost'; @@ -29,6 +31,14 @@ export default function PollResultPage() { }, }); + useEffect(() => { + if (post && result) { + ReactGA.event('poll_result_viewed', { + post_id: postId, + }); + } + }, [post, result, postId]); + if (isPostLoading || isResultLoading) return ; if (!post || !result) return ;