Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 0 additions & 113 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,119 +1,6 @@
<!doctype html>
<html lang="en">
<head>
<style>
body {
overscroll-behavior: none;
touch-action: pan-y pinch-zoom;
}

* {
overscroll-behavior-x: none;
}
</style>
<script>
// 좌우 스와이프 네비게이션 완전 차단
let startX = null;
let startY = null;

document.addEventListener(
'touchstart',
function (e) {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
},
{ passive: false },
);

document.addEventListener(
'touchmove',
function (e) {
if (startX === null || startY === null) return;

let currentX = e.touches[0].clientX;
let currentY = e.touches[0].clientY;
let diffX = Math.abs(currentX - startX);
let diffY = Math.abs(currentY - startY);

// 수평 스와이프 감지시 무조건 차단
if (diffX > 5 && diffX > diffY) {
e.preventDefault();
e.stopPropagation();
return false;
}
},
{ passive: false, capture: true },
);

document.addEventListener(
'touchend',
function (e) {
startX = null;
startY = null;
},
{ passive: false },
);

document.addEventListener(
'touchcancel',
function (e) {
startX = null;
startY = null;
},
{ passive: false },
);

// 추가적인 제스처 차단
document.addEventListener(
'gesturestart',
function (e) {
e.preventDefault();
},
{ passive: false },
);

document.addEventListener(
'gesturechange',
function (e) {
e.preventDefault();
},
{ passive: false },
);

document.addEventListener(
'gestureend',
function (e) {
e.preventDefault();
},
{ passive: false },
);
</script>
<script>
(function (m, a, z, e) {
var s, t;
try {
t = m.sessionStorage.getItem('maze-us');
} catch (err) {}

if (!t) {
t = new Date().getTime();
try {
m.sessionStorage.setItem('maze-us', t);
} catch (err) {}
}

s = a.createElement('script');
s.src = z + '?apiKey=' + e;
s.async = true;
a.getElementsByTagName('head')[0].appendChild(s);
m.mazeUniversalSnippetApiKey = e;
})(
window,
document,
'https://snippet.maze.co/maze-universal-loader.js',
'77efe927-4d36-4c1a-9e5f-b47c9b90fff9',
);
</script>
<script>
function applyVv() {
const vv = window.visualViewport;
Expand Down
10 changes: 9 additions & 1 deletion src/components/common/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { Outlet } from 'react-router-dom';
import { Outlet, useLocation } from 'react-router-dom';
import { useEffect } from 'react';
import ScrollToTop from './ScrollToTop';
import { sendPageView } from '@/lib/ga';

const Layout = () => {
const location = useLocation();

useEffect(() => {
sendPageView(location.pathname + location.search + location.hash);
}, [location.pathname, location.search, location.hash]);

return (
<>
<ScrollToTop />
Expand Down
38 changes: 38 additions & 0 deletions src/lib/ga.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
declare global {
interface Window {
dataLayer: unknown[];
gtag: (...args: unknown[]) => void;
}
}

export const GA_ID = import.meta.env.VITE_GA_MEASUREMENT_ID as string | undefined;

export function initGA() {
if (!GA_ID) return;

// gtag.js 로더 주입
const script = document.createElement('script');
script.async = true;
script.src = `https://www.googletagmanager.com/gtag/js?id=${GA_ID}`;
document.head.appendChild(script);

// gtag 초기화
window.dataLayer = window.dataLayer || [];
window.gtag = function gtag(...args: unknown[]) {
window.dataLayer.push(args);
};

window.gtag('js', new Date());
// SPA라면 초기 자동 page_view는 끄고 필요 시 수동 전송
window.gtag('config', GA_ID, { send_page_view: false });
}

// SPA 라우팅 시 수동 전송용
export function sendPageView(path: string) {
if (!GA_ID || !window.gtag) return;
window.gtag('event', 'page_view', {
page_title: document.title,
page_location: window.location.href,
page_path: path,
});
}
3 changes: 3 additions & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { createRoot } from 'react-dom/client';
import './main.css';
import App from './App.tsx';
import { initGA } from './lib/ga.ts';

initGA();

createRoot(document.getElementById('root')!).render(<App />);