UNPKG

@adstage/web-sdk

Version:

AdStage Web SDK - Production-ready marketing platform SDK with React Provider support for seamless integration

150 lines (128 loc) 5.01 kB
import { DOMUtils } from '../utils/dom-utils'; import { getSDKVersion } from '../utils/version'; import { ConfigUtils } from '../utils/config-utils'; /** * 디바이스 정보 수집 클래스 * - 브라우저 환경 정보 수집 * - 디바이스 ID 생성 및 관리 * - 세션 ID 생성 및 관리 */ export class DeviceInfoCollector { /** * 디바이스 ID 생성 및 반환 (SSR 안전) */ static generateDeviceId(): string { if (!DOMUtils.isBrowser()) return 'ssr_device_' + Date.now(); const stored = localStorage.getItem('adstage_device_id'); if (stored) return stored; const deviceId = 'device_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now(); localStorage.setItem('adstage_device_id', deviceId); return deviceId; } /** * 세션 ID 생성 및 반환 (SSR 안전) */ static generateSessionId(): string { if (!DOMUtils.isBrowser()) return 'ssr_session_' + Date.now(); const stored = sessionStorage.getItem('adstage_session_id'); if (stored) return stored; const sessionId = 'session_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now(); sessionStorage.setItem('adstage_session_id', sessionId); return sessionId; } /** * 모바일 디바이스 여부 확인 (SSR 안전) */ static isMobile(): boolean { if (!DOMUtils.isBrowser()) return false; return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); } /** * 플랫폼 타입 반환 (서버 enum에 맞춤, SSR 안전) */ static getPlatform(): 'ios' | 'android' | 'web' | 'desktop' { if (!DOMUtils.isBrowser()) return 'web'; const userAgent = navigator.userAgent.toLowerCase(); if (/iphone|ipad|ipod/.test(userAgent)) { return 'ios'; } if (/android/.test(userAgent)) { return 'android'; } if (DeviceInfoCollector.isMobile()) { return 'web'; // 모바일 웹 } return 'desktop'; // 데스크톱 웹 } /** * 완전한 디바이스 정보 수집 */ static collectDeviceInfo(): { deviceId: string; sessionId: string; osVersion: string; deviceModel: string; appVersion: string; sdkVersion: string; language: string; country: string; ipAddress: string; userAgent: string; timezone: string; viewportWidth: number; viewportHeight: number; screenWidth: number; screenHeight: number; colorDepth: number; pixelRatio: number; connectionType: string; platform: 'ios' | 'android' | 'web' | 'desktop'; } { const viewportInfo = DOMUtils.getViewportInfo(); return { deviceId: DeviceInfoCollector.generateDeviceId(), sessionId: DeviceInfoCollector.generateSessionId(), osVersion: DOMUtils.isBrowser() ? navigator.platform : 'SSR', deviceModel: DOMUtils.isBrowser() ? navigator.platform : 'SSR', appVersion: '1.0.0', // 기본값 (사용자가 별도 설정 필요) sdkVersion: getSDKVersion(), // package.json에서 동적 로드 language: DOMUtils.isBrowser() ? (navigator.language || 'ko') : 'ko', country: 'KR', // 기본값 ipAddress: '', // 서버에서 자동으로 설정됨 userAgent: DOMUtils.isBrowser() ? navigator.userAgent : 'SSR', timezone: DOMUtils.isBrowser() ? Intl.DateTimeFormat().resolvedOptions().timeZone : 'UTC', viewportWidth: viewportInfo.width, viewportHeight: viewportInfo.height, screenWidth: DOMUtils.isBrowser() ? screen.width : 0, screenHeight: DOMUtils.isBrowser() ? screen.height : 0, colorDepth: DOMUtils.isBrowser() ? screen.colorDepth : 24, pixelRatio: viewportInfo.pixelRatio, connectionType: DOMUtils.isBrowser() ? ((navigator as any).connection?.effectiveType || 'unknown') : 'unknown', platform: DeviceInfoCollector.getPlatform(), }; } /** * 슬롯 위치 정보 가져오기 (SSR 안전) * 슬라이더 내부 광고 요소도 지원 */ static getSlotPosition(containerId: string): string { // 1. 기본 컨테이너 ID로 먼저 찾기 let element = DOMUtils.safeGetElementById(containerId); // 2. 컨테이너를 찾지 못한 경우, 슬라이더 래퍼 찾기 if (!element) { // 슬라이더 래퍼는 일반적으로 원본 컨테이너 내부에 있음 const sliderWrapper = DOMUtils.safeQuerySelector(`#${containerId} .adstage-slider-wrapper`); if (sliderWrapper) { element = sliderWrapper as HTMLElement; } } // 3. 여전히 찾지 못한 경우, data-adstage-slot-id 속성으로 찾기 if (!element) { element = DOMUtils.safeQuerySelector(`[data-adstage-slot-id="${containerId}"]`); } if (!element) return 'unknown'; const rect = element.getBoundingClientRect(); const scrollInfo = DOMUtils.getScrollInfo(); return `x:${Math.round(rect.left)},y:${Math.round(rect.top + scrollInfo.scrollTop)}`; } }