/** * 将所有 inline scripts 迁移到这里以符合 CSP 策略 * 按 DOMContentLoaded 加载顺序执行 */ (function() { 'use strict'; // ════════════════════════════════════════════════════════════════ // 1️⃣ reCAPTCHA 延迟加载 // ════════════════════════════════════════════════════════════════ function initRecaptchaLoader() { let loaded = false; function loadRecaptcha() { if (loaded) return; loaded = true; const script = document.createElement('script'); script.src = 'https://www.google.com/recaptcha/api.js'; script.async = true; script.defer = true; document.head.appendChild(script); console.debug('[reCAPTCHA] 脚本已加载'); } // 当表单区块进入 viewport 下方 300px 时开始加载 if ('IntersectionObserver' in window) { const observer = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting) { loadRecaptcha(); observer.disconnect(); } }, { rootMargin: '0px 0px 300px 0px' } ); document.addEventListener('DOMContentLoaded', () => { const form = document.getElementById('consultation-form'); if (form) { observer.observe(form); } else { loadRecaptcha(); } }); } else { // fallback: 5 秒後加载 setTimeout(loadRecaptcha, 5000); } } // ════════════════════════════════════════════════════════════════ // 2️⃣ Service Worker 註冊 // ════════════════════════════════════════════════════════════════ function initServiceWorker() { if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker .register('/sw.js', { scope: '/' }) .then((reg) => { reg.addEventListener('updatefound', () => { const newWorker = reg.installing; newWorker.addEventListener('statechange', () => { if ( newWorker.state === 'installed' && navigator.serviceWorker.controller ) { console.log('[SW] 新版本已就緒,重新整理後生效'); } }); }); }) .catch((err) => console.warn('[SW] 註冊失敗:', err)); }); } } // ════════════════════════════════════════════════════════════════ // 3️⃣ GA4 事件追蹤 // ════════════════════════════════════════════════════════════════ function initGA4Tracking() { if (typeof gtag === 'undefined') { console.debug('[GA4] gtag 未定义,跳过'); return; } document.addEventListener('DOMContentLoaded', function () { // ── 電話按鈕點擊 ────────────────────────────── document.querySelectorAll('a[href^="tel:"], #float-phone').forEach(function (el) { el.addEventListener('click', function () { gtag('event', 'click_phone', { event_category: 'engagement', event_label: el.href || el.id }); }); }); // ── LINE 按鈕點擊 ────────────────────────────── document.querySelectorAll('a[href*="line.me"], #float-line').forEach(function (el) { el.addEventListener('click', function () { gtag('event', 'click_line', { event_category: 'engagement', event_label: el.href || el.id }); }); }); // ── 表單提交 ────────────────────────────── const forms = document.querySelectorAll('form'); forms.forEach(function (form) { form.addEventListener('submit', function () { const formId = form.id || form.name || '未命名表單'; gtag('event', 'form_submit', { event_category: 'engagement', event_label: formId }); }); }); // ── 樓盤詳情點擊(用於追蹤用戶瀏覽行為) ────────────────────────────── document.querySelectorAll('[data-house-id]').forEach(function (el) { el.addEventListener('click', function () { const houseId = el.getAttribute('data-house-id'); gtag('event', 'view_house_detail', { event_category: 'house_detail', event_label: houseId }); }); }); }); } // ════════════════════════════════════════════════════════════════ // 初始化所有模块 // ════════════════════════════════════════════════════════════════ console.debug('[inline-scripts] 初始化...'); // 在 DOM 完全加载前初始化(early initialization) initRecaptchaLoader(); initServiceWorker(); // 在 DOMContentLoaded 时初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initGA4Tracking); } else { initGA4Tracking(); } })();