feat: Add Analytics component with Umami and Clarity support

- Add Analytics.tsx component for tracking with Umami (self-hosted) and Microsoft Clarity
- Update layout.tsx to include Analytics component
- Environment variables: NEXT_PUBLIC_UMAMI_WEBSITE_ID, NEXT_PUBLIC_CLARITY_ID

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
AutonetSellCar Deploy
2026-02-08 20:14:36 +09:00
parent 346018c4fb
commit fb3f3f6127
2 changed files with 47 additions and 0 deletions

View File

@@ -2,6 +2,7 @@ import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import ClientLayout from '@/components/ClientLayout'
import Analytics from '@/components/Analytics'
const inter = Inter({ subsets: ['latin'] })
@@ -21,6 +22,7 @@ export default function RootLayout({
<ClientLayout>
{children}
</ClientLayout>
<Analytics />
</body>
</html>
)

View File

@@ -0,0 +1,45 @@
'use client';
import { useEffect } from 'react';
import Script from 'next/script';
interface AnalyticsProps {
umamiWebsiteId?: string;
umamiSrc?: string;
clarityId?: string;
}
export default function Analytics({
umamiWebsiteId = process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID,
umamiSrc = process.env.NEXT_PUBLIC_UMAMI_SRC || 'https://analytics.grantech.kr/script.js',
clarityId = process.env.NEXT_PUBLIC_CLARITY_ID,
}: AnalyticsProps) {
// Microsoft Clarity initialization
useEffect(() => {
if (clarityId && typeof window !== 'undefined') {
(function (c: Window & { clarity?: Function }, l: Document, a: string, r: string, i: string) {
(c as any)[a] = (c as any)[a] || function (...args: any[]) {
((c as any)[a].q = (c as any)[a].q || []).push(args);
};
const t = l.createElement(r) as HTMLScriptElement;
t.async = true;
t.src = 'https://www.clarity.ms/tag/' + i;
const y = l.getElementsByTagName(r)[0];
y.parentNode?.insertBefore(t, y);
})(window, document, 'clarity', 'script', clarityId);
}
}, [clarityId]);
return (
<>
{/* Umami Analytics */}
{umamiWebsiteId && (
<Script
src={umamiSrc}
data-website-id={umamiWebsiteId}
strategy="afterInteractive"
/>
)}
</>
);
}