import * as amplitude from '@amplitude/analytics-browser' import type { AnalyticsDetailType, AnalyticsLogDataTracking } from '../types/AnalyticsType' import type { PageDataResourceGroup } from '#layers/types/api/pageData' import type { IdentityInfo, ActionInfo, MarketingInfo } from '../types/Stove81Plug' declare const svcLog: any declare const twq: any declare const ttq: any /** * 페이지 데이터와 템플릿 정보를 기반으로 분석용 로그 데이터를 생성하는 composable * @param resourcesData 페이지 리소스 데이터 * @param pageVerTmplSeq 템플릿 시퀀스 번호 * @returns 분석용 로그 데이터 객체 */ export const useAnalyticsLogData = ( resourcesData: PageDataResourceGroup, pageVerTmplSeq: number ) => { const store = usePageDataStore() const pageData = store.pageData if (!pageData) { return ref({} as AnalyticsDetailType) } const pageDataTrack = (typeof resourcesData.tracking === 'object' ? resourcesData.tracking : {}) as AnalyticsLogDataTracking console.log("🚀 ~ useAnalyticsLogData ~ pageDataTrack:", pageData) const logData = ref({ actionType: pageDataTrack?.action_type, // logSourceType:pageDataTrack.logSourceType, // viewArea:pageDataTrack.viewArea, // viewType:pageDataTrack.viewType, clickArea:pageData.page_name_en, clickSarea: pageData.templates[pageVerTmplSeq].page_ver_tmpl_name_en, clickItem: `${pageData.templates[pageVerTmplSeq].page_ver_tmpl_name}_${pageDataTrack?.click_item}`, event: pageData.page_name, eventCategory: `${pageData.page_name}_${pageDataTrack?.click_item}`, template_code: pageData.templates[pageVerTmplSeq].template_code, page_ver_tmpl_name: pageData.templates[pageVerTmplSeq].page_ver_tmpl_name, page_ver_tmpl_name_en: pageData.templates[pageVerTmplSeq].page_ver_tmpl_name_en, } as unknown as AnalyticsDetailType) return logData } // target에 {XX1, XX2}와 같은 형태가 포함되어 있을 경우 options.clickItem으로부터 값 추출하여 세팅 const findValueFromOption = (target: string, { options = {} }: any) => { if (target.includes('{') && target.includes('}')) { const strTargetClickItem = target.substring(target.indexOf('{') + 1, target.indexOf('}')) const arrTargetClickItem = strTargetClickItem.split(',') const arrTargetClickItemValue = [] for (let targetClickItem of arrTargetClickItem) { targetClickItem = targetClickItem.trim() arrTargetClickItemValue.push(options.clickItem[targetClickItem]) } target = target.replaceAll(`{${strTargetClickItem}}`, arrTargetClickItemValue.join(',')) } return target } /** * Google Analytics 전송 * * @param {AnalyticsDetailType} analytics * @param {object} options */ const sendGA = (analytics: AnalyticsDetailType, { options = {} }: any) => { console.log("🚀 ~ 1111 sendGA ~ analytics:", analytics) try { const { gtag } = useGtag() const eventName = analytics.event || '' const eventLocale = analytics.eventLocale || '' const eventCategory = `${analytics.eventCategory}` // GA 클릭 이벤트 명 뒤에 언어 값 추가 노출되도록 개발. ex) GNB_자유게시판_KO const eventLabel = `${eventCategory}_${eventLocale}` gtag('set', 'cookie_domain', `${window?.location?.hostname || ''}`) // env 값으로 설정 시 쿠키 생성 안 돼서 window.location.hostname으로 설정 gtag('set', 'cookie_expires', '0') // 0으로 설정 시 쿠키가 Session 기반 쿠키로 전환 gtag('event', `${eventName}`, { event_category: eventLabel }) } catch (e) { console.error('[Exception] useAnalytics.sendGA: ', e) } } /** * Stove Analytics(81 Plug) 전송 * * @param {AnalyticsDetailType} analytics * @param {string} mcode * @param {object} options */ const sendSA = (analytics: AnalyticsDetailType, { mcode = '', options = {} }: any) => { const gameDataStore = useGameDataStore() const { gameData } = storeToRefs(gameDataStore) try { const gameNo = gameData.value.game_code const device = useDevice() const deviceType = device.isDesktop ? 'pcweb' : 'mobileweb' const country = `${csrGetCountry()}` const memberNo = `${csrGetStoveMemberNo()}` const actionType = analytics.actionType || '' const logSourceType = analytics.logSourceType || '' const viewArea = analytics.viewArea || '' const viewType = analytics.viewType || '' const clickArea = analytics.clickArea || '' const clickSarea = findValueFromOption(analytics.clickSarea || '', { options }) const eventLocale = analytics.eventLocale || '' const identityInfo: IdentityInfo = { app_id: 'stove', log_source_type: logSourceType, country, locale: eventLocale, lang_cd: eventLocale, member_no: memberNo, channeling_cd: 'SO' } const marketingInfo: MarketingInfo = { marketing_code: mcode || '', device_type: deviceType, media_type: '', media_page: '' } let actionParam = {} if (actionType === 'view') { actionParam = { view_area: viewArea, view_type: viewType, view_info: { game_no: gameNo, lang_cd: eventLocale, ...options?.viewInfo } } } else if (actionType === 'click') { actionParam = { click_area: clickArea, click_sarea: clickSarea, click_item: { click_item: analytics.clickItem, game_no: gameNo, lang_cd: eventLocale, ...options?.clickItem } } } const actionInfo: ActionInfo = { action_type: actionType, action_param: actionParam, marketing_info: marketingInfo } const amplitudeActionInfo = { ...actionInfo, url: `${location?.href || ''}`, agent: `${navigator?.userAgent || ''}` } const amplitudeActionParams: { event_type: string event_properties: ActionInfo & { url: string; agent: string } } = { event_type: actionType, event_properties: amplitudeActionInfo } svcLog.identity(identityInfo) svcLog.action(actionInfo, {}, {}) // 81plug warning log 제거를 위해 2번째 인자부터 빈 객체 세팅 amplitude.track(amplitudeActionParams) } catch (e) { console.error('[Exception] useAnalytics.sendSA: ', e) } } /** * 기본 로그 일괄 전송 * * @param {string} locale * @param {AnalyticsDetailType} analytics */ const sendLog = (locale: string, analytics: AnalyticsDetailType) => { console.log("🚀 ~ sendLog ~ analytics:", analytics) // 언어 코드 대문자 변환 analytics.eventLocale = locale.toUpperCase() if (analytics) { // GA 전송 : eventCategory 유무로 판별 sendGA(analytics, { options: analytics.options }) // SA 전송 : actionType, logSourceType 유무로 판별 if ( analytics.actionType && analytics.actionType !== '' // analytics.logSourceType && // analytics.logSourceType !== '' ) { sendSA(analytics, { mcode: analytics.mcode, options: analytics.options }) } } } /** * Google Analytics 전송 (기본 이벤트만 전송) * * @param {string} gaEventName */ const sendGAEventOnly = (gaEventName: string) => { try { const { gtag } = useGtag() gtag('set', 'cookie_domain', `${window?.location?.hostname || ''}`) // env 값으로 설정 시 쿠키 생성 안 돼서 window.location.hostname으로 설정 gtag('set', 'cookie_expires', '0') // 0으로 설정 시 쿠키가 Session 기반 쿠키로 전환 gtag('event', `${gaEventName}`) } catch (e) { console.error('[Exception] useAnalytics.sendGAEventOnly: ', e) } } /** * 메타 픽셀 전송 * * @param {string} fbEventName * @description 수집 대상 페이지에 useHead({ meta: [loadMetaPixelMeta()] }) 선언 */ const sendMetaPixel = (fbEventName: string) => { try { const { $fbq } = useNuxtApp() if (typeof $fbq === 'function') { $fbq('trackCustom', fbEventName) } } catch (e) { console.error('[Exception] useAnalytics.sendMetaPixel: ', e) } } /** * X(트위터) 픽셀 전송 * * @param {string} twEventName * @description 수집 대상 페이지에 useHead({ script: [loadTwitterPixelScript()] }) 선언 */ const sendTwitterPixel = (twEventName: string) => { try { twq('event', twEventName, {}) } catch (e) { console.error('[Exception] useAnalytics.sendTwitterPixel: ', e) } } /** * 틱톡 픽셀 전송 * * @param {string} ttEventName * @description 수집 대상 페이지에 onMounted(() => { loadTikTokPixelScript() }) 선언 */ const sendTiktokPixel = (ttEventName: string) => { try { ttq.track(ttEventName) } catch (e) { console.error('[Exception] useAnalytics.sendTiktokPixel: ', e) } } /** * 마케팅 인텔리전스 팀 요청 마케팅 스크립트 일괄 전송 * * @param {string} gaEventName * @param {string} fbEventName * @param {string} twEventName * @param {string} ttEventName */ const sendMarketingScript = ({ gaEventName, fbEventName, twEventName, ttEventName }: { gaEventName?: string fbEventName?: string twEventName?: string ttEventName?: string }) => { if (gaEventName) { sendGAEventOnly(gaEventName) } if (fbEventName) { sendMetaPixel(fbEventName) } if (twEventName) { sendTwitterPixel(twEventName) } if (ttEventName) { sendTiktokPixel(ttEventName) } } export default () => { return { sendGA, sendSA, sendLog, sendMarketingScript, useAnalyticsLogData } }