JavaScript 标签管理器中的纯 JavaScript 内部促销

Pure JavaScript Internal Promotions in Google Tag Manager

我的任务是创建一个纯 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)
  );
}

然后我抓取页面上所有我想检查的元素是否在视图中,并将它们推送到一个数组中。

这是我用来执行此操作的脚本。 N.B。我在列表上执行了模数除法,因为页面上还有其他项目满足 select 或者我只想 select 每个第 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;
    }
}

然后我想检查这些元素中的每一个是否在用户视口中,因为他们在构建要使用以下脚本推送到数据层的电子商务对象时滚动:

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);
        }
    }

}

我目前的问题是,每当我滚动时,我都会反复检查所有满足我的 select 的项目,或者这意味着直到某个项目不再出现在视口中,我才会将相同的项目推送到dataLayer 多次。

有什么办法可以吗:

A - 停止在每次用户滚动时将相同的项目推送到数据层,只推送一次

B - 压缩我的代码,使其不在三个单独的脚本中

非常感谢您抽出时间查看此内容!

A) 您可以使用布尔值来检测是否已执行数据层推送,如下所示:

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 个单独的脚本中的原因是什么?