我的任务是创建一个纯JS内部推广跟踪器,并通过GTM实现这一点。我不确定我是否以一种非常复杂的方式完成了这项工作,或者不对任何建议持开放态度。
目前我有以下标签:
此函数检查稍后引用的元素是否在视口中
function isInViewport(element) {
var rect = element.getBoundingClientRect();
var html = document.documentElement;
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || html.clientHeight) &&
rect.right <= (window.innerWidth || html.clientWidth)
);
}
然后我抓住我要查看的页面上的所有元素,并将它们推送到数组中。
这是我用来做这个的脚本。注:我在列表上执行了模数除法,因为页面上有其他项目满足该选择器,但我只想选择每个第5项。
var id = document.getElementById('foo');
var list = id.getElementsByTagName('ba');
var items = [];
var position = [];
var j = 1;
for (var i = 0; i < list.length; i++) {
if (i % 5 == 0) {
items.push(list[i]);
j = j + 1;
}
}
然后我想检查这些元素是否在用户视口中滚动,同时使用以下脚本构建要推送到dataLayer的电子商务对象:
window.onscroll = myfunction;
var ecommerceObject;
var event;
function myfunction() {
for (var i = 0; i < cars.length; i++) {
if (isInViewport(list[i]) === true) {
ecommerceObject['ecommerce']['promoView'] = {
'event' : 'promoview',
'promotions': [{
'id': items[i].innerText.split("\n")[1],
'name': items[i].id
}]
};
window.dataLayer.push(ecommerceObject);
}
}
}
我现在的问题是,每当我滚动时,我会反复检查所有满足我的选择器的项目,这意味着在项目不再出现在视口中时,我会多次将相同的项目推送到dataLayer。
无论如何我可以:
A - 每次用户滚动时都停止将相同的项目推送到dataLayer并且只推送一次
B - 压缩我的代码,使其不在三个单独的脚本中
非常感谢您花时间来看看这个!
答案 0 :(得分:1)
A)您可以使用布尔值来检测是否已执行dataLayer push,如下所示:
window.onscroll = myfunction;
var ecommerceObject;
var event;
var done = false; // example of a new variable
function myfunction() {
for (var i = 0; i < cars.length; i++) {
if (isInViewport(list[i]) === true && !done) { //execute only if NOT done
done = true; //set done to true
ecommerceObject['ecommerce']['promoView'] = {
'event' : 'promoview',
'promotions': [{
'id': items[i].innerText.split("\n")[1],
'name': items[i].id
}]
};
window.dataLayer.push(ecommerceObject);
}
}
}
B)首先在3个单独的脚本中使用它的原因是什么?