import { encrypt, decrypt, setCookie, getCookie, deleteCookies, validatePurchaseData, } from './utils' export interface Ipurchase { AdNm: string // 광고주명 ordNo: string // 주문번호 itemId: string // 상품ID itemNm: string // 상품명 sellprc: number // 판매가격 ordAmt: number // 주문금액 dcAmt: number // 할인가격 rlordAmt: number // 실주문금액 rlordQty: number // 실주문갯수 ordState: string // 주문상태 ordDate: string // 주문일자 Commission: number // 수수료 ordUniqNo?: string // 주문고유번호 updateDate?: string // 수정일자 Apclid?: string // 앱클릭아이디 ChNm?: string // 매체명 } const CPS_CONVERSION_URL = 'https://cps-web.stcps.com/api/v1/cps/conversion' function getQueryParam(param: string): string | null { const urlParams = new URLSearchParams(window.location.search) return urlParams.get(param) } function _sendConversion( data: object, apclid: string, chNm: string, cookiesToDelete: string[], ): void { fetch(`${CPS_CONVERSION_URL}?apclid=${apclid}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Channel-Name': chNm, }, body: JSON.stringify(data), }) .then((response) => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`) } return response.json() }) .then(() => { if (cookiesToDelete.length > 0) { deleteCookies(...cookiesToDelete) console.log('삭제 후 쿠키 확인:', document.cookie) } }) .catch((error) => { console.error('전송 중 오류 발생:', error) }) } function init(): void { //Common const gbClick = getQueryParam('gb_click') const gbMedia = getQueryParam('gb_media') const affp1 = getQueryParam('affp1') const affp2 = getQueryParam('affp2') const affp3 = getQueryParam('affp3') const affp4 = getQueryParam('affp4') const affp5 = getQueryParam('affp5') //애드픽 클릭키 const adpickClick = getQueryParam('apclid') const originCookieValue = `${adpickClick}` const originEncryptedValue = encrypt(originCookieValue) //쿠키오븐 클릭키 const cookieovenClick = getQueryParam('click_key') // ✅ delete 조건: linkD 포함 OR utm_source 정확히 gb_cps const urlHasLinkD = window.location.href.includes('linkD') const utmSource = getQueryParam('utm_source') const shouldDeleteCookies = urlHasLinkD || (utmSource !== null && utmSource !== 'gb_cps') //url내 linkD 있거나 utm_source 정확히 gb_cps가 아닌것들들 if (adpickClick && gbClick && gbMedia) { //링크디세션삭제 sessionStorage.removeItem('yuja_real__shopping_partners_referral_code') //adpick & gb 둘다있을경우 const newCookieValue = `${gbMedia}_${gbClick}` const encryptedValue = encrypt(newCookieValue) //커스텀 const affpParams: Record = { affp1, affp2, affp3, affp4, affp5, } //필터링 const affpEntries = Object.entries(affpParams) .filter(([_, value]) => value) .map(([key, value]) => `${key}=${value}`) //삭제 (모든 CPS 쿠키 — 라스트 어트리뷰션) deleteCookies('gb_cps', 'apclid', 'affp_data', 'ADPICKCPS', 'cookieoven_click', 'cookieoven_idfa', 'cookieoven_gaid', 'appier_click', 'appier_idfa', 'appier_gaid', 'waveads_click', 'kakaopages_click', 'geniuscom_click') //새로 생성 setCookie('gb_cps', encryptedValue, 24) setCookie('apclid', originEncryptedValue, 24) if (affpEntries.length > 0) { const affpCookieValue = affpEntries.join('&') setCookie('affp_data', affpCookieValue, 24) } } else if (adpickClick && !gbClick && !gbMedia) { //gbClick,gbMedia 는없고 adpickClick만있는경우 //adpick만있는경우 (라스트 어트리뷰션) deleteCookies('gb_cps', 'apclid', 'affp_data', 'ADPICKCPS', 'cookieoven_click', 'cookieoven_idfa', 'cookieoven_gaid', 'appier_click', 'appier_idfa', 'appier_gaid', 'waveads_click', 'kakaopages_click', 'geniuscom_click') setCookie('apclid', originEncryptedValue, 24) } else if (cookieovenClick) { //쿠키오븐 클릭 — 라스트 어트리뷰션: 기존 모든 CPS 쿠키 초기화 후 저장 const coIdfa = getQueryParam('idfa') const coGaid = getQueryParam('gaid') deleteCookies('gb_cps', 'apclid', 'affp_data', 'ADPICKCPS', 'cookieoven_click', 'cookieoven_idfa', 'cookieoven_gaid', 'appier_click', 'appier_idfa', 'appier_gaid', 'waveads_click', 'kakaopages_click', 'geniuscom_click') setCookie('cookieoven_click', cookieovenClick, 24) if (coIdfa) setCookie('cookieoven_idfa', coIdfa, 24) if (coGaid) setCookie('cookieoven_gaid', coGaid, 24) } else if (getQueryParam('short_id')) { //Appier 클릭 — 라스트 어트리뷰션: 기존 모든 CPS 쿠키 초기화 후 저장 const appierShortId = getQueryParam('short_id') as string const appierIdfa = getQueryParam('idfa') const appierGaid = getQueryParam('gaid') deleteCookies('gb_cps', 'apclid', 'affp_data', 'ADPICKCPS', 'cookieoven_click', 'cookieoven_idfa', 'cookieoven_gaid', 'appier_click', 'appier_idfa', 'appier_gaid', 'waveads_click', 'kakaopages_click', 'geniuscom_click') setCookie('appier_click', appierShortId, 24) if (appierIdfa) setCookie('appier_idfa', appierIdfa, 24) if (appierGaid) setCookie('appier_gaid', appierGaid, 24) } else if (getQueryParam('waclick')) { //Waveads 클릭 — 라스트 어트리뷰션: 기존 모든 CPS 쿠키 초기화 후 저장 deleteCookies('gb_cps', 'apclid', 'affp_data', 'ADPICKCPS', 'cookieoven_click', 'cookieoven_idfa', 'cookieoven_gaid', 'appier_click', 'appier_idfa', 'appier_gaid', 'waveads_click', 'kakaopages_click', 'geniuscom_click') setCookie('waveads_click', getQueryParam('waclick') as string, 24) const waAffpEntries = Object.entries({ affp1, affp2, affp3, affp4, affp5 }) .filter(([_, v]) => v) .map(([k, v]) => `${k}=${v}`) if (waAffpEntries.length > 0) { setCookie('affp_data', waAffpEntries.join('&'), 24) } } else if (getQueryParam('callbackParams')) { //카카오페이지 클릭 — 라스트 어트리뷰션: 기존 모든 CPS 쿠키 초기화 후 저장 deleteCookies('gb_cps', 'apclid', 'affp_data', 'ADPICKCPS', 'cookieoven_click', 'cookieoven_idfa', 'cookieoven_gaid', 'appier_click', 'appier_idfa', 'appier_gaid', 'waveads_click', 'kakaopages_click', 'geniuscom_click') setCookie('kakaopages_click', getQueryParam('callbackParams') as string, 24) } else if (getQueryParam('gc')) { //지니어스컴 클릭 — 라스트 어트리뷰션: 기존 모든 CPS 쿠키 초기화 후 저장 deleteCookies('gb_cps', 'apclid', 'affp_data', 'ADPICKCPS', 'cookieoven_click', 'cookieoven_idfa', 'cookieoven_gaid', 'appier_click', 'appier_idfa', 'appier_gaid', 'waveads_click', 'kakaopages_click', 'geniuscom_click') setCookie('geniuscom_click', getQueryParam('gc') as string, 24) } else if (shouldDeleteCookies) { //linkD 포함하거나 utm_source값이 있고 gb_cps가 아니면 쿠키삭제 deleteCookies('gb_cps', 'apclid', 'affp_data', 'ADPICKCPS', 'cookieoven_click', 'cookieoven_idfa', 'cookieoven_gaid', 'appier_click', 'appier_idfa', 'appier_gaid', 'waveads_click', 'kakaopages_click', 'geniuscom_click') } } function getCookieValue(): string | null { const encryptedValue = getCookie('gb_cps') return encryptedValue ? decrypt(encryptedValue) : null } function originGetCookieValue(): string | null { const originEncryptedValue = getCookie('apclid') return originEncryptedValue ? decrypt(originEncryptedValue) : null } function purchase(data: Ipurchase) { const adpickCpsCookie = getCookie('apclid') const cookieovenCookie = getCookie('cookieoven_click') const appierClickCookie = getCookie('appier_click') const waveadsClickCookie = getCookie('waveads_click') const kakaopagesClickCookie = getCookie('kakaopages_click') const geniuscomClickCookie = getCookie('geniuscom_click') if (!adpickCpsCookie && !cookieovenCookie && !appierClickCookie && !waveadsClickCookie && !kakaopagesClickCookie && !geniuscomClickCookie) { return } //gb_cps쿠키담기기 const gbCpsCookie = getCookie('gb_cps') if (gbCpsCookie) { const decryptedValue = decrypt(gbCpsCookie as string) const firstUnderscoreIndex = decryptedValue.indexOf('_') data.Apclid = decryptedValue.slice(firstUnderscoreIndex + 1) data.ChNm = decryptedValue.slice(0, firstUnderscoreIndex) } //affp쿠키가져오기 const affpCookie = getCookie('affp_data') if (affpCookie) { const affpParams = Object.fromEntries( affpCookie.split('&').map((entry) => entry.split('=')), ) Object.assign(data, affpParams) //`affp_data` 값을 `data` 객체에 추가 } console.log('data : ', data) const validationError = validatePurchaseData(data) if (validationError) { console.warn(validationError) return } const apclid = data.Apclid ?? '' const chNm = data.ChNm ?? '' const sendData = { ...data } delete sendData.Apclid delete sendData.ChNm //애드픽/GB 전환 전송 if (adpickCpsCookie) { _sendConversion(sendData, apclid, chNm, ['gb_cps', 'apclid', 'affp_data', 'ADPICKCPS']) } //쿠키오븐 전환 전송 (기존 로직과 독립적으로 동작) if (cookieovenCookie) { const coData = { ...sendData } const coIdfa = getCookie('cookieoven_idfa') const coGaid = getCookie('cookieoven_gaid') if (coIdfa) (coData as Record).idfa = coIdfa if (coGaid) (coData as Record).gaid = coGaid _sendConversion(coData, cookieovenCookie, 'cookieoven', ['cookieoven_click', 'cookieoven_idfa', 'cookieoven_gaid']) } //Appier 전환 전송 — short_id 파라미터로 랜딩한 경우 if (appierClickCookie) { const appierData = { ...sendData } const appierIdfa = getCookie('appier_idfa') const appierGaid = getCookie('appier_gaid') if (appierIdfa) (appierData as Record).idfa = appierIdfa if (appierGaid) (appierData as Record).gaid = appierGaid _sendConversion(appierData, appierClickCookie, 'appier', ['appier_click', 'appier_idfa', 'appier_gaid']) } //Waveads 전환 전송 — waclick 파라미터로 랜딩한 경우 if (waveadsClickCookie) { _sendConversion(sendData, waveadsClickCookie, 'waveads', ['waveads_click']) } //카카오페이지 전환 전송 — callbackParams 파라미터로 랜딩한 경우 if (kakaopagesClickCookie) { _sendConversion(sendData, kakaopagesClickCookie, 'kakaopages', ['kakaopages_click']) } //지니어스컴 전환 전송 — gc 파라미터로 랜딩한 경우 if (geniuscomClickCookie) { _sendConversion(sendData, geniuscomClickCookie, 'geniuscom', ['geniuscom_click']) } } function purchaseCancel(data: Ipurchase) { // 구매취소는 purchase 성공 후 쿠키가 이미 삭제된 상태이므로 쿠키 체크 없이 전송 // Kafka consumer에서 ordNo로 원본 구매 건과 매핑 console.log('purchaseCancel data : ', data) const validationError = validatePurchaseData(data) if (validationError) { console.warn(validationError) return } const sendData = { ...data } delete sendData.Apclid delete sendData.ChNm _sendConversion(sendData, '', '', []) } // 자동 실행 (사용자가 직접 호출할 필요 없이 작동) init() export default { init, getCookieValue, originGetCookieValue, purchase, purchaseCancel }