feat. 페이지 분석 로그 데이터 기능 추가 및 컴포넌트 수정

This commit is contained in:
“hyeonggkim”
2025-10-01 21:41:47 +09:00
parent 5f140aced1
commit 5646c2501b
9 changed files with 78 additions and 25 deletions

View File

@@ -7,6 +7,7 @@ import type { ButtonType } from '#layers/types/components/button'
interface ButtonListProps { interface ButtonListProps {
resourcesData: PageDataResourceGroup[] resourcesData: PageDataResourceGroup[]
pageVerTmplSeq: number
} }
const props = defineProps<ButtonListProps>() const props = defineProps<ButtonListProps>()
@@ -51,7 +52,13 @@ const getButtonProps = (button: PageDataResourceGroup) => ({
}), }),
disabled: button.btn_info?.disabled, disabled: button.btn_info?.disabled,
text: button.btn_info?.txt_btn_name, text: button.btn_info?.txt_btn_name,
tracking: button.tracking,
}) })
const { useAnalyticsLogDataDirect } = useAnalytics()
// const logData = useAnalyticsLogDataDirect(props.resourcesData, props.pageVerTmplSeq)
console.log("🚀 11111~ getButtonProps ~ props.resourcesData:", getButtonProps(props.resourcesData[0]))
</script> </script>
<template> <template>
@@ -63,6 +70,7 @@ const getButtonProps = (button: PageDataResourceGroup) => ({
v-for="(button, index) in props.resourcesData" v-for="(button, index) in props.resourcesData"
:key="`${button.group_code}-${index}`" :key="`${button.group_code}-${index}`"
v-bind="getButtonProps(button)" v-bind="getButtonProps(button)"
v-analytics="useAnalyticsLogDataDirect(getButtonProps(button), props.pageVerTmplSeq)"
class="size-extra-small md:size-medium" class="size-extra-small md:size-medium"
> >
{{ button.btn_info?.txt_btn_name }} {{ button.btn_info?.txt_btn_name }}

View File

@@ -5,8 +5,8 @@ const props = defineProps<{
resourcesData: PageDataResourceGroup resourcesData: PageDataResourceGroup
pageVerTmplSeq: number pageVerTmplSeq: number
}>() }>()
const { useAnalyticsLogData } = useAnalytics() const { useAnalyticsLogDataDirect } = useAnalytics()
const logData = useAnalyticsLogData(props.resourcesData, props.pageVerTmplSeq) const logData = useAnalyticsLogDataDirect(props.resourcesData, props.pageVerTmplSeq)
// YouTube 모달 스토어 사용 // YouTube 모달 스토어 사용
const modalStore = useModalStore() const modalStore = useModalStore()
@@ -20,6 +20,7 @@ const handleVideoPlayClick = () => {
<template> <template>
<AtomsButtonPlay <AtomsButtonPlay
v-analytics="logData"
:resources-data="resourcesData" :resources-data="resourcesData"
@click="handleVideoPlayClick" @click="handleVideoPlayClick"
/> />

View File

@@ -25,7 +25,6 @@ export const useAnalyticsLogData = (
} }
const pageDataTrack = (typeof resourcesData.tracking === 'object' ? resourcesData.tracking : {}) as AnalyticsLogDataTracking const pageDataTrack = (typeof resourcesData.tracking === 'object' ? resourcesData.tracking : {}) as AnalyticsLogDataTracking
console.log("🚀 ~ useAnalyticsLogData ~ pageDataTrack:", pageData)
const logData = ref({ const logData = ref({
actionType: pageDataTrack?.action_type, actionType: pageDataTrack?.action_type,
@@ -45,6 +44,43 @@ export const useAnalyticsLogData = (
return logData return logData
} }
/**
* 페이지 데이터와 템플릿 정보를 기반으로 분석용 로그 데이터를 생성하는 composable (직접 객체 반환)
* @param resourcesData 페이지 리소스 데이터
* @param pageVerTmplSeq 템플릿 시퀀스 번호
* @returns 분석용 로그 데이터 객체 (ref 없이)
*/
export const useAnalyticsLogDataDirect = (
resourcesData: PageDataResourceGroup,
pageVerTmplSeq: number
) => {
const store = usePageDataStore()
const pageData = store.pageData
if (!pageData) {
return {} as AnalyticsDetailType
}
const pageDataTrack = (typeof resourcesData.tracking === 'object' ? resourcesData.tracking : {}) as AnalyticsLogDataTracking
const logData = {
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으로부터 값 추출하여 세팅 // target에 {XX1, XX2}와 같은 형태가 포함되어 있을 경우 options.clickItem으로부터 값 추출하여 세팅
const findValueFromOption = (target: string, { options = {} }: any) => { const findValueFromOption = (target: string, { options = {} }: any) => {
@@ -70,7 +106,6 @@ const findValueFromOption = (target: string, { options = {} }: any) => {
* @param {object} options * @param {object} options
*/ */
const sendGA = (analytics: AnalyticsDetailType, { options = {} }: any) => { const sendGA = (analytics: AnalyticsDetailType, { options = {} }: any) => {
console.log("🚀 ~ 1111 sendGA ~ analytics:", analytics)
try { try {
const { gtag } = useGtag() const { gtag } = useGtag()
@@ -98,7 +133,8 @@ const sendGA = (analytics: AnalyticsDetailType, { options = {} }: any) => {
* @param {string} mcode * @param {string} mcode
* @param {object} options * @param {object} options
*/ */
const sendSA = (analytics: AnalyticsDetailType, { mcode = '', options = {} }: any) => { const sendSA = (analytics: AnalyticsDetailType, { mcode = '', options: _options = {} }: any) => {
console.log("🚀 ~44444 sendSA ~ analytics:", analytics)
const gameDataStore = useGameDataStore() const gameDataStore = useGameDataStore()
const { gameData } = storeToRefs(gameDataStore) const { gameData } = storeToRefs(gameDataStore)
@@ -116,7 +152,7 @@ const sendSA = (analytics: AnalyticsDetailType, { mcode = '', options = {} }: an
const viewArea = analytics.viewArea || '' const viewArea = analytics.viewArea || ''
const viewType = analytics.viewType || '' const viewType = analytics.viewType || ''
const clickArea = analytics.clickArea || '' const clickArea = analytics.clickArea || ''
const clickSarea = findValueFromOption(analytics.clickSarea || '', { options }) const clickSarea = findValueFromOption(analytics.clickSarea || '', { _options })
const eventLocale = analytics.eventLocale || '' const eventLocale = analytics.eventLocale || ''
const identityInfo: IdentityInfo = { const identityInfo: IdentityInfo = {
@@ -145,7 +181,7 @@ const sendSA = (analytics: AnalyticsDetailType, { mcode = '', options = {} }: an
view_info: { view_info: {
game_no: gameNo, game_no: gameNo,
lang_cd: eventLocale, lang_cd: eventLocale,
...options?.viewInfo ..._options?.viewInfo
} }
} }
} else if (actionType === 'click') { } else if (actionType === 'click') {
@@ -156,7 +192,7 @@ const sendSA = (analytics: AnalyticsDetailType, { mcode = '', options = {} }: an
click_item: analytics.clickItem, click_item: analytics.clickItem,
game_no: gameNo, game_no: gameNo,
lang_cd: eventLocale, lang_cd: eventLocale,
...options?.clickItem ..._options?.clickItem
} }
} }
} }
@@ -196,7 +232,7 @@ const sendSA = (analytics: AnalyticsDetailType, { mcode = '', options = {} }: an
* @param {AnalyticsDetailType} analytics * @param {AnalyticsDetailType} analytics
*/ */
const sendLog = (locale: string, analytics: AnalyticsDetailType) => { const sendLog = (locale: string, analytics: AnalyticsDetailType) => {
console.log("🚀 ~ sendLog ~ analytics:", analytics) console.log("🚀 ~33333 sendLog ~ analytics:", analytics)
// 언어 코드 대문자 변환 // 언어 코드 대문자 변환
@@ -313,5 +349,5 @@ const sendMarketingScript = ({
} }
export default () => { export default () => {
return { sendGA, sendSA, sendLog, sendMarketingScript, useAnalyticsLogData } return { sendGA, sendSA, sendLog, sendMarketingScript, useAnalyticsLogData, useAnalyticsLogDataDirect }
} }

View File

@@ -17,7 +17,6 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
try { try {
const pageUrl = getPathAfterLanguage(to.path) const pageUrl = getPathAfterLanguage(to.path)
console.log('🚀 ~ pageUrl:', pageUrl)
// pageUrl이 빈값이거나 null이면 /brand로 리다이렉트 // pageUrl이 빈값이거나 null이면 /brand로 리다이렉트
if (!pageUrl || pageUrl === '' || pageUrl === '/') { if (!pageUrl || pageUrl === '' || pageUrl === '/') {
@@ -30,7 +29,7 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
page_url: pageUrl, page_url: pageUrl,
_t: Date.now().toString(), // 캐시 무효화를 위한 타임스탬프 _t: Date.now().toString(), // 캐시 무효화를 위한 타임스탬프
} }
console.log('🚀 ~ queryParams:', queryParams) // console.log('🚀 ~ queryParams:', queryParams)
const response = (await commonFetch('GET', apiUrl, { const response = (await commonFetch('GET', apiUrl, {
query: queryParams, query: queryParams,
@@ -39,7 +38,7 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
if (response?.code === 0 && 'value' in response) { if (response?.code === 0 && 'value' in response) {
store.setPageData(response.value) store.setPageData(response.value)
console.log('🚀 ~ cleanData:', response.value) // console.log('🚀 ~ cleanData:', response.value)
} else { } else {
store.clearPageData() store.clearPageData()
} }

View File

@@ -85,6 +85,7 @@ const handleChange = (
<WidgetsButtonList <WidgetsButtonList
v-if="buttonListData" v-if="buttonListData"
:resources-data="buttonListData" :resources-data="buttonListData"
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
class="mt-[40px] md:mt-[56px]" class="mt-[40px] md:mt-[56px]"
/> />
</div> </div>

View File

@@ -102,6 +102,7 @@ const handleChange = (
<WidgetsButtonList <WidgetsButtonList
v-if="buttonListData" v-if="buttonListData"
:resources-data="buttonListData" :resources-data="buttonListData"
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
class="mt-[32px]" class="mt-[32px]"
/> />
</div> </div>

View File

@@ -43,17 +43,22 @@ const buttonListData = computed(() =>
:resources-data="descriptionData" :resources-data="descriptionData"
class="w-[355px] md:w-[944px]" class="w-[355px] md:w-[944px]"
/> />
<client-only>
<WidgetsVideoPlay <WidgetsVideoPlay
v-if="videoPlayData" v-if="videoPlayData"
:resources-data="videoPlayData" :resources-data="videoPlayData"
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)" :page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
/> />
</client-only>
<client-only>
<WidgetsButtonList <WidgetsButtonList
v-if="buttonListData.length > 0" v-if="buttonListData.length > 0"
:resources-data="buttonListData" :resources-data="buttonListData"
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
button-type="market" button-type="market"
class="mt-[22px] md:mt-[52px]" class="mt-[22px] md:mt-[52px]"
/> />
</client-only>
</div> </div>
</section> </section>
</template> </template>

View File

@@ -105,6 +105,7 @@ const slideItemSize = {
<WidgetsButtonList <WidgetsButtonList
v-if="buttonListData.length > 0" v-if="buttonListData.length > 0"
:resources-data="buttonListData" :resources-data="buttonListData"
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
class="mt-[48px] md:mt-[72px]" class="mt-[48px] md:mt-[72px]"
/> />
<BlocksSlideCenterHighlight <BlocksSlideCenterHighlight

View File

@@ -49,6 +49,7 @@ const props = defineProps<Props>()
<WidgetsButtonList <WidgetsButtonList
v-if="hasComponentGroup(item, 'buttonList')" v-if="hasComponentGroup(item, 'buttonList')"
:resources-data="getComponentGroupAry(item, 'buttonList')" :resources-data="getComponentGroupAry(item, 'buttonList')"
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
class="mt-[28px] md:mt-[52px]" class="mt-[28px] md:mt-[52px]"
/> />
</div> </div>