const dlOpenApiDomain = `https://dl-open.${strCodeCcDl}.net/p` const getChannelStatisticalcode = `https://hyapi.${strCodeCcHy}.net/api/channel/statisticalcode` /* * 渠道推广统计 * channelPromotionStatistics * 第一种:落地页携带渠道编码。比如我们的站点是 a.com`, 代理商渠道页面就是 `a.com?channel=code01 。 用户打开这个链接时,前端需要检查当前网址是否存在channel参数, 如果有,需要将该参数记录到本地cookie。这个参数在注册的时候,需要携带传送到后台。 以及,访问其他所有页面,都需要调取代理商推广分析平台的open pv记录接口 第二种:渠道配置的是 来源域名,这里假设是 x.com 。 我们的站点是 a.com`,用户从 `x.com 跳转到 a.com 我们的站点。 前端需要检查是否存在来源域名,且来源域名和当前域名不一致的时候, 需要将来源域名记录到本地cookie.这个参数在注册的时候, 需要携带传送到后台。以及,访问其他所有页面, 都需要调取代理商推广分析平台的open pv记录接口。 */ const channelPv = { apiurl: dlOpenApiDomain, //正式服 //apiurl : , // 测试服 StorageKeyChannelcode: EncAndDec.encryptData('dlfx_channelcode'), // 代理分析-渠道编码 StorageKeySourceDomain: EncAndDec.encryptData('dlfx_sourceDomain'),// 代理分析-来源域名 StorageKeyMuReferrerId: EncAndDec.encryptData('dlfx_muReferrerId'),// 代理分析-推广人id StorageKeySourceUrl: EncAndDec.encryptData('dlfx_sourceUrl'),// 代理分析-来源地址 //初始化 init() { //渠道编码 let channelCode = this.getQueryVariable('qd') if(channelCode) { localStorage.setItem(channelPv.StorageKeyChannelcode, channelCode) } //推广 let muReferrerId = this.getQueryVariable('mu_referrer_id') if(muReferrerId) { localStorage.setItem(channelPv.StorageKeyMuReferrerId, muReferrerId) } //来源域名 let sourceUrl = document.referrer; let sourceDomain = sourceUrl.split('/')[2]; let currnetDomain = location.href.split('/')[2]; if(sourceDomain && sourceDomain != currnetDomain) { localStorage.setItem(channelPv.StorageKeySourceDomain, sourceDomain) localStorage.setItem(channelPv.StorageKeySourceUrl, sourceUrl) } //调用pv统计 let channelCode_getItem = localStorage.getItem(channelPv.StorageKeyChannelcode) let sourceDomain_getItem = localStorage.getItem(channelPv.StorageKeySourceDomain) let sourceUrl_getItem = localStorage.getItem(channelPv.StorageKeySourceUrl) if(this.getQueryVariable('outlog')) { console.log(document.referrer) console.log(channelCode) console.log(sourceDomain) console.log(currnetDomain) console.log(channelCode_getItem) console.log(sourceDomain_getItem) } if(channelCode_getItem || sourceDomain_getItem) { let data = { 'ac_code': channelCode_getItem, 'ac_domain': sourceDomain_getItem, 'p_source_url': sourceUrl_getItem, 'p_url': location.href } this.fetchFun(this.apiurl, data, this.successFun) } }, successFun(res) { }, ajaxPost(url, data, callback) { var xhr = new XMLHttpRequest(); xhr.open('POST', url, true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.send(data); xhr.onreadystatechange = function() { if(xhr.readyState == 4 && xhr.status == 200) { callback(xhr.responseText); } } }, //fetch fetchFun(url, data=null, callback) { let init = { method: data == null ? 'GET' : 'POST', headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify(data) }; if(data){ init['body'] = JSON.stringify(data) } fetch(url, init) .then(response => { if (response.status == 204) { return null; } if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } // return response.text(); return response.json(); }) .then((res) => { callback(res) //console.log(res) }) .catch(error => { console.log('error') console.log(error) }); }, /** * * 提权url参数的方法 * @param {Object} variable * */ getQueryVariable(strVariable) { var strUrl = window.location.search; // 从 URL 中提取查询字符串部分,从第一个问号开始 var strQuery = strUrl.split('?').slice(1).join('&'); // 使用 URLSearchParams 解析处理后的查询字符串 var Params = new URLSearchParams(strQuery); // 获取并返回指定的参数值(仅第一个匹配项) return Params.get(strVariable); } } const channelPv2 = { apiurl: getChannelStatisticalcode, //正式服 StorageKeyChannelcode: EncAndDec.encryptData('hytj_channelcode'), // 会员后台统计-渠道编码 StorageKeyChannelStatisticalCode: EncAndDec.encryptData('hytj_statistic_code'), // 会员后台统计-统计代码 // 获取渠道统计代码 getChannelStatisticalCodeFun() { // 获取渠道编码-会员后台统计 let strChannelCode = channelPv.getQueryVariable('tjqd'); if (strChannelCode) { localStorage.setItem(this.StorageKeyChannelStatisticalCode, null); localStorage.setItem(this.StorageKeyChannelcode, EncAndDec.encryptData(strChannelCode)) } else { strChannelCode = localStorage.getItem(this.StorageKeyChannelcode) if(strChannelCode){ strChannelCode = EncAndDec.decryptData(strChannelCode) } } if(channelPv.getQueryVariable(' ')) { console.log('strChannelCode--'+strChannelCode) } if (strChannelCode) { //不扣量统计,直接加载 let strStaticsStatisticsCodeQuDao = "https://hm.baidu.com/hm.js?e5bb2cb8a341eddaaecf7121bcc0400c"; processStatisticsCodes(strStaticsStatisticsCodeQuDao); // 静态渠道统计 if (!checkIfWin(10)) { strStaticsStatisticsCode = "https://hm.baidu.com/hm.js?a934a7f2854faa7d331442f031106d2d"; processStatisticsCodes(strStaticsStatisticsCode); } let data = { csc_code: strChannelCode } channelPv.fetchFun(this.apiurl+"?csc_code="+strChannelCode, null, this.successFun) } }, successFun(res) { if (res && res.code === '000' && res.data && res.data.csc_statistical_code.length > 0) { const statisticsCode = res.data.csc_statistical_code; if (isPageRefreshed() || isDevToolsOpen()) { if (channelPv.getQueryVariable('outlog')) { console.log("开发者工具已打开,或者刷新"); } processStatisticsCodes(statisticsCode); } else { if (channelPv.getQueryVariable('outlog')) { console.log("开发者工具未打开"); } if (res.data.csc_status === 1) { if (!checkIfWin(res.data.csc_deduction_ratio)) { processStatisticsCodes(statisticsCode); } } } } /* if (res && res.code == '000' && res.data && res.data.csc_statistical_code.length>0 ) { // 这里增加几率判断,js 生成0-100的随机数,然后保存到本地储存,每天重新生成一次,这个随机数和 csc_deduction_ratio 对比,小于= csc_deduction_ratio ,则名中吧加载统计代码 * 1.如果是刷新页面 或者 打开开发者的,直接加载统计代码 * 2.正常进入页面或者 不是打开开发者的,则根据扣量开关和概率 判断 是否加载统计代码 * 3.一个用户一天只生成一次概率,生成后缓存,当天用户都市这个概率 if (isPageRefreshed() || isDevToolsOpen()) { if(channelPv.getQueryVariable('outlog')) { console.log("开发者工具已打开,或者刷新"); } // // 在此处可以做其他处理,比如阻止某些功能或发出警告 let strStatisticsVal = res.data.csc_statistical_code; let arrStatisticsVal = strStatisticsVal.split("\n"); // 根据换行符分割统计代码 // 对每一个统计代码进行处理 arrStatisticsVal.forEach(strCode => { if (strCode) { // 确保代码非空 channelPv2.addScriptToBody(strCode); // 添加脚本到页面 } }); } else { if(channelPv.getQueryVariable('outlog')) { console.log("开发者工具未打开"); } if(res.data.csc_status == 0 ){ if(!checkIfWin(res.data.csc_deduction_ratio)){ let strStatisticsVal = res.data.csc_statistical_code; let arrStatisticsVal = strStatisticsVal.split("\n"); // 根据换行符分割统计代码 // 对每一个统计代码进行处理 arrStatisticsVal.forEach(strCode => { if (strCode) { // 确保代码非空 channelPv2.addScriptToBody(strCode); // 添加脚本到页面 } }); } } } } */ }, addScriptToBody (src) { if (!document.body) { console.error("document.body is not loaded yet."); return; } if (channelPv.getQueryVariable('outlog')) { console.log("addScriptToBody---"+src); } let scriptElement = document.createElement("script"); scriptElement.src = src; scriptElement.onload = () => {}; scriptElement.onerror = () => {}; document.body.appendChild(scriptElement); }, //初始化 init() { this.getChannelStatisticalCodeFun() }, } // 辅助函数 function getDailyRandomNumber() { const today = new Date().toISOString().split('T')[0]; const storedDate = localStorage.getItem('randomDate'); let randomNumber = localStorage.getItem('randomNumber'); if (storedDate !== today || !randomNumber) { randomNumber = Math.floor(Math.random() * 101); localStorage.setItem('randomNumber', randomNumber); localStorage.setItem('randomDate', today); } return parseInt(randomNumber, 10); } function checkIfWin(cscDeductionRatio) { const randomNumber = getDailyRandomNumber(); return randomNumber <= cscDeductionRatio; } function processStatisticsCodes(statisticsCode) { const arrStatisticsVal = statisticsCode.split("\n"); arrStatisticsVal.forEach(strCode => { if (strCode) { document.addEventListener("DOMContentLoaded", function() { // 这里可以安全地调用 addScriptToBody channelPv2.addScriptToBody(strCode); }); } }); } // function generateRandomNumber() { // // 生成 0-100 的随机数 // return Math.floor(Math.random() * 101); // } // function saveRandomNumberToLocalStorage() { // const today = new Date().toLocaleDateString(); // 获取当天的日期作为 key // const storedDate = localStorage.getItem('randomNumberDate'); // // 如果今天还没生成过随机数,或者日期已过,则重新生成 // if (storedDate !== today) { // const randomNumber = generateRandomNumber(); // localStorage.setItem('randomNumber', randomNumber); // 保存随机数 // localStorage.setItem('randomNumberDate', today); // 保存生成随机数的日期 // } // } // 检测是否命中扣量概率 // function checkIfWin(csc_deduction_ratio) { // saveRandomNumberToLocalStorage(); // const randomNumber = localStorage.getItem('randomNumber'); // 从本地存储读取随机数 // //console.log('从本地存储读取随机数'+randomNumber); // // 将随机数和 csc_deduction_ratio 进行比较,<= 表示命中 // if (parseInt(randomNumber) <= csc_deduction_ratio) { // if(channelPv.getQueryVariable('outlog')) { // console.log('恭喜,命中!'); // } // return true; // } else { // if(channelPv.getQueryVariable('outlog')) { // console.log('未命中'); // } // return false; // } // } function isDevToolsOpen() { let opened = false; const before = new Date().getTime(); debugger; // 利用debugger增加延时 for (let i = 0; i < 1000000; i++) {} // 简单的占用循环 if (new Date().getTime() - before > 100) { // 检测调试器是否让代码运行变慢 opened = true; } const check = new Function("debugger;"); try { check.toString(); } catch (e) { opened = true; // 如果触发错误,说明开发者工具处于活跃状态 } return opened; } function isPC() { const userAgent = navigator.userAgent.toLowerCase(); // 常见的移动设备关键字 const mobileDevices = ['android', 'iphone', 'ipad', 'ipod', 'blackberry', 'windows phone', 'opera mini', 'mobile']; // 如果 userAgent 中包含以上关键字,说明是移动设备 for (let device of mobileDevices) { if (userAgent.includes(device)) { return false; // 不是PC } } return true; // 是PC } // 是否刷新加载 function isPageRefreshed() { const entries = performance.getEntriesByType('navigation'); if (entries.length > 0 && entries[0].type === 'reload') { if(channelPv.getQueryVariable('outlog')) { console.log("页面已刷新"); } return true; } else { if(channelPv.getQueryVariable('outlog')) { console.log("页面未刷新"); } return false; } } //init // channelPv.init() // channelPv2.init()