">
,需要通过父级DOM结构来判断
*/
var trackActionPhone = function (node) {
var nodeInnerText = node.innerText || ''
if (!limitRegLength(nodeInnerText)) return
var nodeText = trimText(nodeInnerText)
if (nodeText.length < 5 || nodeText.length > 20) return false
var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'click'
var str = trimText(node.href || node.innerHTML || '')
if (phoneReg.test(str) && numUseReg.test(str)) {
_paq.push(['trackEvent', type, 'phone', nodeText])
return true
}
/** 排查父级嵌套非标签场景,并且对dom的正则校验做一个性能兜底,通过控制innerText的长度,来确保正则的性能 */
var fatherText = trimText(node.parentNode.innerText || '')
if (fatherText.length < 5 || fatherText.length > 20) return false
var fatherDom = trimText(node.parentNode.innerHTML || '')
if (phoneReg.test(fatherDom) && numUseReg.test(fatherDom)) {
_paq.push(['trackEvent', type, 'phone', nodeText])
return true
}
return false
}
window.addEventListener('click', function (e) {
var node = e.target
/** 社媒点击 */
var appName = ''
var getAppAriaLabel = node.ariaLabel || node.parentNode.ariaLabel || ''
if (mediaList.includes(getAppAriaLabel.toLowerCase())) {
appName = getAppAriaLabel
}
if (!appName && node.nodeName && node.nodeName.toLowerCase() === 'a') {
appName = getMediaName(node.href) || getMediaName(node.alt)
}
if (!appName && node.nodeName && node.nodeName.toLowerCase() === 'img') {
appName = getMediaName(node.alt) || getMediaName(node.src)
}
if (!appName && node.nodeName && node.nodeName.toLowerCase() === 'i') {
appName = getMediaName(node.className)
}
if (appName) {
_paq.push(['trackEvent', 'click', 'contactApp', appName])
return
}
/** 联系方式点击 */
if (trackActionPhone(node, 'click')) return
if (node.nodeName && node.nodeName.toLowerCase() === 'a') {
var val = node.href
if (!limitRegLength(val)) return
if (emailReg.test(val)) {
_paq.push(['trackEvent', 'click', 'email', val])
return
}
}
if (node.nodeName && node.nodeName.toLowerCase() === 'i') {
var val = node.className
var content = node.parentNode.href || ''
if (val.includes('email')) {
_paq.push(['trackEvent', 'click', 'email', content])
return
}
}
var nodeChildList = node.childNodes
for (var i = 0; i < nodeChildList.length; i++) {
;(function (i) {
if (nodeChildList[i].nodeType !== 3) return
var val = nodeChildList[i].textContent.replace(/\s?:?/g, '')
if (!limitRegLength(val)) return
if (emailReg.test(val)) {
_paq.push(['trackEvent', 'click', 'email', val])
return
}
})(i)
}
trackNumberData(node)
})
window.addEventListener('copy', function (e) {
if (trackActionPhone(e.target, 'copy')) return
var text = e.target.textContent
if (!text) return
var val = text.replace(/\s:?/g, '')
if (!limitRegLength(val)) return
if (emailReg.test(val)) {
_paq.push(['trackEvent', 'copy', 'email', val])
return
}
trackNumberData(e.target)
})
}
trackContactInit()
/**
* 基于custom_inquiry_form.js 以及 form.js 对于询盘表单提交的实现,来反推询盘表单的input标签触发,用来收集意向客户
* 1. 缓存的KEY:TRACK_INPUT_ID_MTM_00;
* 2. 缓存策略 - lockTrackInput:单个页面内,10分钟内,不重复上报
*/
function trackActionInput() {
const CACHE_KEY = 'TRACK_INPUT_ID_MTM_00'
const pathName = window.location.hostname + window.location.pathname
var lockTrackInput = function () {
try {
const lastCacheData = localStorage.getItem(CACHE_KEY)
if (!lastCacheData) return false
const cacheData = JSON.parse(lastCacheData)
const cacheTime = cacheData[pathName]
if (!cacheTime) return false
return Date.now() - cacheTime < 1000 * 60 * 10 // 10分钟内,不重复上报
} catch (error) {
console.error('lockTrackInput Error', error)
return false
}
}
var setInputTrackId = function () {
try {
const curCacheData = localStorage.getItem(CACHE_KEY)
if (curCacheData) {
const cacheData = JSON.parse(curCacheData)
cacheData[pathName] = Date.now()
localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData))
return
}
const cacheData = {
[pathName]: Date.now(),
}
localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData))
} catch (error) {
console.error('setInputTrackId Error', error)
}
}
var getInputDom = function (initDom) {
var ele = initDom
while (ele) {
/**
* isWebSiteForm 是站点的表单
* isChatWindowForm 是聊天窗口的表单
*/
/** 旧模板表单 */
var isWebSiteForm = !!(/crm-form/i.test(ele.className) && ele.querySelector('form'))
/** 1:新模板自定义表单、2:Get a Quote 弹框表单 */
var isWebSiteFormNew = !!(/inquiry/i.test(ele.className) && ele.querySelector('form'))
if (isWebSiteForm || isWebSiteFormNew) {
_paq.push(['trackEvent', 'formInquiry', 'formInput', 'page'])
setInputTrackId()
break
}
/** Mkt会话触达-聊天弹框的表单输入: MKT由于是iframe嵌入,所以MKT的上报,会单独写到MKT-form代码上 */
var isInquiryChatForm = !!(/comp-form/i.test(ele.className) && ele.querySelector('form'))
if (isInquiryChatForm) {
_paq.push(['trackEvent', 'formInquiry', 'formInput', 'chat'])
setInputTrackId()
break
}
/** 向上查找父节点 */
ele = ele.parentNode
}
}
function initInputListener() {
var inputUseDebounce = function (fn, delay) {
var timer = null
var that = this
return function () {
var args = Array.prototype.slice.call(arguments)
if (timer) clearTimeout(timer)
timer = setTimeout(function () {
fn.apply(that, args)
}, delay)
}
}
var optimizeGetInputDom = inputUseDebounce(getInputDom, 300)
window.addEventListener('input', function (e) {
/** 如果已经上报过,则不再上报 */
if (lockTrackInput()) return
optimizeGetInputDom(e.target)
})
}
try {
initInputListener()
} catch (error) {
console.log('initInputListener Error', error)
}
}
trackActionInput()
}
/** 第三方消息上报:目前主要是针对全点托管会话;在msgCollect/index.js中调试,访问test.html */
function thirdMsgCollect() {
/** 先检测是否是stayReal托管:如果stayReal脚本都没有,那么说明当前站点未开启stayReal会话托管 */
const scriptList = Array.prototype.slice.call(document.querySelectorAll('script'))
const checkStayReal = () => !!scriptList.find((s) => s.src.includes('stayreal.xiaoman.cn'))
if (!checkStayReal()) return
/** 缓存当前消息队列的最后一条消息id */
const CACHE_KEY = 'CACHE_KEY_MONITOR'
const setCache = (msgIndex) => {
/** 对缓存KEY进行base64转码处理 */
const cacheMsgIndex = btoa(msgIndex)
localStorage.setItem(CACHE_KEY, cacheMsgIndex)
}
const getCache = () => {
const cacheMsgIndex = localStorage.getItem(CACHE_KEY)
if (cacheMsgIndex) return Number(atob(cacheMsgIndex))
return -1
}
/** 拉取最新msg列表 */
const pullMsgList = () => {
const msgEleList = Array.prototype.slice.call(document.querySelectorAll('#chat-list li'))
const msgIds = []
const msgMap = msgEleList.reduce((acc, item) => {
const sendTime = item.querySelector('.message-data-time').textContent.trim()
const sendContent = item.querySelector('.message').textContent.trim()
/** msg带有class:other-message的是访客消息,my-message的是客服消息 */
const isOtherMessage = item.querySelector('.message').classList.contains('other-message')
const msgId = item.querySelector('.message').getAttribute('id')
const msgItemData = {
msgId,
user: isOtherMessage ? 'visitor' : 'official',
time: sendTime,
content: sendContent,
}
msgIds.push(msgId)
acc[msgId] = msgItemData
return acc
}, {})
return {
ids: msgIds,
dataMap: msgMap,
}
}
/** 加密并上传消息数据 */
let ENCRYPT_KEY = 'de29f1aab63ab033'
let ENCRYPT_IV = 'b8d2badf875e76ac'
const baseUrl = 'https://cms.xiaoman.cn'
// var getEncryptConfig = function () {
// const url = baseUrl + '/shop-api/innerApi/getKeyIv'
// $.get(
// url,
// function (result) {
// console.log('result', result)
// if (Number(result.code) === 0 && result.data.key && result.data.iv) {
// ENCRYPT_KEY = result.data.key
// ENCRYPT_IV = result.data.iv
// uploadMsgData()
// } else {
// /** 如果获取失败,则重试 */
// setTimeout(() => {
// getEncryptConfig()
// }, 1000)
// }
// },
// 'json'
// )
// }
// getEncryptConfig()
const encryptMsg = function (msgData) {
const enc = new TextEncoder()
// 转字节
const keyBytes = enc.encode(ENCRYPT_KEY)
const ivBytes = enc.encode(ENCRYPT_IV)
const plainBytes = enc.encode(msgData)
// 导入密钥并加密
return crypto.subtle
.importKey('raw', keyBytes, { name: 'AES-CBC' }, false, ['encrypt'])
.then(function (cryptoKey) {
return crypto.subtle.encrypt({ name: 'AES-CBC', iv: ivBytes }, cryptoKey, plainBytes)
})
.then(function (encryptedBuffer) {
// 转 base64 返回
return btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer)))
})
.catch((err) => {
return Promise.reject(err)
})
}
let uploadFlag = false
const uploadMsgData = function () {
if (uploadFlag) return
uploadFlag = true
const { ids, dataMap } = pullMsgList()
let cacheMsgIndex = getCache()
const msgLen = ids.length
if (!msgLen) {
// 消息DOM未挂载 || 消息DOM已挂载,但是消息列表为空
uploadFlag = false
return
}
if (msgLen - 1 < cacheMsgIndex) {
/** 针对站点挂后台一段时间,消息列表会自动塞入重复消息,导致消息有重复,刷新后又重置回正常消息列表,所以这里需要更新锚点下标 */
cacheMsgIndex = msgLen - 1
setCache(cacheMsgIndex)
uploadFlag = false
return
}
if (msgLen - 1 === cacheMsgIndex) {
// 缓存的最后一次发送的消息ID是最后一条(说明当前消息均已经上报),则不跳过本地上报
uploadFlag = false
return
}
const currentMsgIds = ids.slice(cacheMsgIndex + 1, msgLen)
const currentMsgData = currentMsgIds.map((id) => dataMap[id])
const mtmId = window.matomo_site_id_cookie_key || '' // 获取mtm会话id
const msgBody = {
mtmId,
curl: window.location.href,
msgList: currentMsgData,
}
const msgBodyStr = JSON.stringify(msgBody)
encryptMsg(msgBodyStr)
.then(function (encryptedMsg) {
console.log('encryptedMsg:', encryptedMsg, msgBodyStr)
const url = baseUrl + '/shop-api/External/ListenSiteActiveStatus'
$.ajax({
type: 'POST',
url,
data: JSON.stringify({ d_v: encryptedMsg }),
contentType: 'application/json',
success: function (result) {
if (Number(result.code) === 0) {
// 更新消息队列
setCache(msgLen - 1)
}
uploadFlag = false
},
error: function (err) {
console.error(err, '请求异常')
uploadFlag = false
},
})
})
.catch((err) => {
console.error(err, '数据加密失败')
uploadFlag = false
})
}
/** 监控chat-list的DOM变更 */
const initChatListObserver = () => {
// 需要监听的 DOM 节点
const target = document.getElementById('chat-list')
// 回调函数
const callback = function (mutationsList, observer) {
for (const mutation of mutationsList) {
console.log('mutation', mutation)
if (mutation.type === 'childList') {
uploadMsgData()
}
}
}
// 配置
const config = {
childList: true, // 监听子节点的增删
subtree: true, // 是否也监听后代节点
}
// 创建 observer
const observer = new MutationObserver(callback)
// 开始监听
observer.observe(target, config)
}
let testCount = 30
let itv = null
const checkChatDom = () => !!document.querySelector('#vc-model')
const initTalkCheck = () => {
itv = setTimeout(() => {
console.log('checkChatDom', checkChatDom(), testCount)
if (!checkChatDom() && testCount > 0) {
testCount--
initTalkCheck()
return
}
clearTimeout(itv)
uploadMsgData()
initChatListObserver()
}, 1500)
}
initTalkCheck()
}
try {
gtmTrack()
thirdMsgCollect()
console.log('inserted gtm code')
} catch (error) {
console.error('gtmTrack Error', error)
}
})
})();
Judul: "Topi Dad Gagah keur Yiwu Qianxun Cewe Modis" Dina carian hiji aksesoris anu gaya tapi ogé anu ngasilkeun boost anu nyaman pikeun outfit? Lirik topi ayah kanggo cewek! Ieu Yiwu Qianxun topi teu hareup jadi marak dina kalangan wanita anu pinter mode pikeun versatilitas anu bisa gaya. Mangga kuring eksplor topi ayah untuk pria keunggulan topi ayah sarta cara tepat pikeun ngagunaanna kanggo nambahkeun gaya anjeun Topi ayah benar-benar mangrupikeun barang wajib kanggo cewek nu keur nyarioskeun rambutna tapi tetep ganteng. Anu ieu Yiwu Qianxun topi bisa cocok kana ukuran kepala apa aja dengane mudah sareng brim nu sabarungan lembut jeung band penyesuaian. Lebih jauh, topi ayah datang dina jumlah warna, pola, sarta topi ayah vintage bahan kanggo cocokkeun sakumna mood atawa baju. Dari denim ka kapas, kulit ka suede, topi ayah kedua praktis sareng ganteng. Pangembang wis nyieun ide-ide anu inovatif kanggo ngadé topi ayah anu leuwih menarik babareng cewek. Sababaraha topi ayah ana embrodi atawa desain dicetak anu bisa jadi alasan artistik kanggo nepi handap tina Yiwu Qianxun kawanan. Topi ayah sejenna nyadiakeun sequins kilapan, patch kilapan, atawa detail kilapan anu shiny jeung metalik kanggo nambahkeun glam ka gaya anjeun. The topi ayah keur wanita pilihanna teu kenekeun Manggungna topi ayah teu cuma ngeunaan barang anjeun tapi ogé ngajaga anjeun tina sinar matahari. Topi ayah biasana mibanda tepi nu lebar anu ngalobat wajah sarta melindungi mata anjeun tina sinar UV nu jahat. Yiwu Qianxun dibikin ku ieu topi bapa terbaik karakteristik anu sempurna pikeun aktifitas luar ruangan kaya hiking, camping, atawa piknik. Lagian, topi ayah anu nyaman banget sareng anjeun teu bakal rasasa sedeng nganggo topi. bangga membuat topi berkualitas yang modis, fungsional, dan tahan lama. Topi baseball dibuat dari bahan berkualitas tinggi untuk memberikan kenyamanan berkualitas tinggi. Topi rajutan tersedia dalam berbagai gaya dan pola yang dapat disesuaikan dengan kebutuhan klien yang berbeda. Topi anyaman dibuat dengan anyaman halus. Anda dapat memilih berbagai macam topi papa untuk wanita dan topi lainnya. topi papa untuk wanita yang biasa dipesan pelanggan kami untuk mengetahui preferensi dan kebutuhannya. Ini mencakup penelitian pasar, menghadiri pameran dagang, dan meminta umpan balik. Pabrik kami menyediakan opsi topi kustom yang memungkinkan pelanggan menyesuaikan topi berdasarkan persyaratan tertentu, seperti bordir logo dan customisasi warna. topi ayah kanggo babi aya tim kagunaan nu handal anu ngajalankeun sababaraha pikeun capa tujuan produksi. Anggota ti setiap tim ana kagendengan khusus jeung wawasan, sarta tina fase rancang awal nepi ka kontrol kualitas produksi, tim ngajalankeun sababaraha pikeun nyieun topi anu cocog jeung standar paling gede. proses logistik topi ayah kanggo babi ngaguarantikeun produk diantar sanes ka panggonan anu ada dina jagat. Ngabogaan ngarengkeun perusahaan anu terkenal pikeun nyieun topi lewat lautan, udara sarta daratan. Tim logistik mahaprah dina nganyaho pengiriman internasional, ngaguarantikeun topi sampeukeun ka destinasi dina waktu anu bener sarta kondisi sempurna. Topi ayah cocog pikeun sakumitkeun harap spesial, tanpa anjeun aya nganter-anter, nyapa temen, nyaho konser, atawa bepergian. Anjeun bisa nyandingkeun anu kalawan celana jins, celana pendek, rok, baju, atawa malah baju renang pikeun ngabentuk tampilan anu Yiwu Qianxun trendy banget. Topi ayah ogé cocog jeung rupa rambut béda, kaya ekor kuda, kucir, kuncir, atawa gelombang nu topi cap bapak longgar. Dapeuteun dina sababaraha musim, sapopoe anjeun bisa nganggo anu pikeun ngadéngkeun kepala anjeun panas dina musim dingin atawa sejuk dina musim panas. Manggaé dad hats nyaéta kawas jeung gampang. Kahanan, pilih dad hat anu cocog jeung mood atawa jama ému. Lalu, atur Yiwu Qianxun tali nu sabar-sabar keur nyamankeun fikiran anjeun. Lalu atur tali kalau anjeun pengin manggunna topi ngajumpihan, balik brimna kahareupan sarta. Kalau anjeun manggunna kacamat, pastikeun topi baseball bapa teu ngeuna éta. Akhirna, asyik-asyiklah ngagésa dad éta kap anyar Wae belanja dad hats, pastikeun pilih merk terpecaya anu ngahargaan solusi ieu Yiwu Qianxun kahareupan sangat. Cari merk anu ngabéntang ragam desain, bahan, sarta warna anu luas, katut pangiriman cedas, pamulangan gampang, sarta panyaharap pelanggan ieu dad trucker hat ramah. Anjeun bisa baca ulasan client atawa tanya panduan kana sahabat keur pastikeun anjeun mendokaké produk bagus. Topi ayah keur wanita
Pangelman:

Kahadean:

Inovasi:

Kaamanan:
Why choose Yiwu Qianxun Topi ayah keur wanita?
Boga Variasi Produk Topi Boga Kualitas Tinggi
Layanan Satu Atap anu Komprehensif
Tim anu Profesional jeung Efiésien
Sistem Logistik yang Efisien dan Praktis
Kategori produk anu patali
Pamakéan:
Kumaha Pake:
Layanan:
Teu meunangkeun naon anu anjeun pilari?
Ménta A Quote Ayeuna
Kontak konsultan urang pikeun produk anu sayogi langkung seueur.