diff --git a/src/app/providers.tsx b/src/app/providers.tsx
index c47a52a1..6be0fa11 100644
--- a/src/app/providers.tsx
+++ b/src/app/providers.tsx
@@ -6,19 +6,22 @@ import RootStyleRegistry from "./RootStyleRegistry";
import { GlobalErrorBoundary } from "@/components/errorHandling/GlobalErrorBoundary";
import { ViewTransitions } from "next-view-transitions";
import PageNavigationProvider from "@/context/PageNavigationProvider";
+import { AnalyticsProvider } from "@/context/AnalyticsProvider";
export default function Providers({ children }: { children: ReactNode }) {
return (
-
-
-
-
+
+
+
+
+
- {children}
-
-
-
+ {children}
+
+
+
+
);
}
diff --git a/src/context/AnalyticsProvider.tsx b/src/context/AnalyticsProvider.tsx
new file mode 100644
index 00000000..dfb9f83b
--- /dev/null
+++ b/src/context/AnalyticsProvider.tsx
@@ -0,0 +1,86 @@
+"use client";
+
+import { createContext, useContext, useEffect, ReactNode } from "react";
+import { usePathname, useSearchParams } from "next/navigation";
+import Script from "next/script";
+import { GA_TRACKING_ID, pageview, event } from "@/utils/gtag";
+
+interface AnalyticsContextType {
+ trackPageView: (pageName?: string) => void;
+ trackClick: (elementName: string, additionalData?: Record) => void;
+}
+
+const AnalyticsContext = createContext(undefined);
+
+interface AnalyticsProviderProps {
+ children: ReactNode;
+}
+
+export function AnalyticsProvider({ children }: AnalyticsProviderProps) {
+ const pathname = usePathname();
+ const searchParams = useSearchParams();
+
+ // 자동 페이지 뷰 추적
+ useEffect(() => {
+ if (GA_TRACKING_ID) {
+ const url = pathname + (searchParams.toString() ? `?${searchParams.toString()}` : "");
+ pageview(url);
+ }
+ }, [pathname, searchParams]);
+
+ const trackPageView = (pageName?: string) => {
+ if (GA_TRACKING_ID) {
+ const name = pageName || pathname.replace("/", "") || "home";
+ event("page_view", {
+ page_title: name,
+ page_location: window.location.href,
+ page_path: pathname,
+ });
+ }
+ };
+
+ const trackClick = (elementName: string, additionalData?: Record) => {
+ if (GA_TRACKING_ID) {
+ event("click", {
+ event_category: "engagement",
+ event_label: elementName,
+ page_path: pathname,
+ ...additionalData,
+ });
+ }
+ };
+
+ return (
+
+ {/* Google Analytics Scripts */}
+ {GA_TRACKING_ID && (
+ <>
+
+
+ >
+ )}
+ {children}
+
+ );
+}
+
+export const useAnalytics = () => {
+ const context = useContext(AnalyticsContext);
+ if (context === undefined) {
+ throw new Error("useAnalytics must be used within an AnalyticsProvider");
+ }
+ return context;
+};
diff --git a/src/hooks/useClickTracking.tsx b/src/hooks/useClickTracking.tsx
new file mode 100644
index 00000000..84dcf44d
--- /dev/null
+++ b/src/hooks/useClickTracking.tsx
@@ -0,0 +1,15 @@
+import { useCallback } from "react";
+import { useAnalytics } from "@/context/AnalyticsProvider";
+
+export const useClickTracking = () => {
+ const { trackClick } = useAnalytics();
+
+ const track = useCallback(
+ (elementName: string, additionalData?: Record) => {
+ trackClick(elementName, additionalData);
+ },
+ [trackClick]
+ );
+
+ return { track };
+};
diff --git a/src/hooks/usePageTracking.tsx b/src/hooks/usePageTracking.tsx
new file mode 100644
index 00000000..6e92230d
--- /dev/null
+++ b/src/hooks/usePageTracking.tsx
@@ -0,0 +1,14 @@
+"use client";
+
+import { useEffect } from "react";
+import { useAnalytics } from "@/context/AnalyticsProvider";
+
+export const usePageTracking = (pageName?: string) => {
+ const { trackPageView } = useAnalytics();
+
+ useEffect(() => {
+ if (pageName) {
+ trackPageView(pageName);
+ }
+ }, [pageName, trackPageView]);
+};
diff --git a/src/page/Home/Home.tsx b/src/page/Home/Home.tsx
index 6f78c73a..3936b8a8 100644
--- a/src/page/Home/Home.tsx
+++ b/src/page/Home/Home.tsx
@@ -16,9 +16,13 @@ import { isGuestUser } from "@/utils/user";
import { useRouter } from "next/navigation";
import axios from "axios";
+import { usePageTracking } from "@/hooks/usePageTracking";
+import { useClickTracking } from "@/hooks/useClickTracking";
const Home = () => {
const { name } = myPageStore();
+ usePageTracking("home");
+ const { track } = useClickTracking();
const { setSearchTravel, setNotification } = useBackPathStore();
const router = useRouter();
console.log();
@@ -41,6 +45,7 @@ const Home = () => {
// 이 부분 추후 유저 id로 대채해야함
const onClickAlarm = () => {
+ track("알림 링크", { link_text: "알림 페이지" });
setNotification("/");
router.push(`/notification`);
};
diff --git a/src/utils/gtag.ts b/src/utils/gtag.ts
new file mode 100644
index 00000000..cea9d6e9
--- /dev/null
+++ b/src/utils/gtag.ts
@@ -0,0 +1,15 @@
+export const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS || "";
+
+export const pageview = (url: string) => {
+ if (typeof window !== "undefined" && window.gtag) {
+ window.gtag("config", GA_TRACKING_ID, {
+ page_path: url,
+ });
+ }
+};
+
+export const event = (action: string, parameters?: Record) => {
+ if (typeof window !== "undefined" && window.gtag) {
+ window.gtag("event", action, parameters);
+ }
+};