Files
SEONexus/code/public/template/shikong/js/channel.min.js
2025-04-22 17:43:00 +08:00

411 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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()