在Tag Manager JS中监听dataLayer推送事件的事件监听器

4

我想添加一个自定义脚本,将其集成到现有页面的Tag Manager数据层中。我需要该脚本被通知新的dataLayer数据推送。

因此,每当页面上使用window.dataLayer.push时,我的脚本应该得到通知。

是否有一种方法可以向Google Script API中添加自定义的dataLayer事件监听器?

我正在寻找类似于:

google_tag_manager.dataLayer.onPush(callback);
google_tag_manager.dataLayer.subscribers 似乎列出了有多少 dataLayer 订阅者 - 但我应该如何添加我的订阅者?
3个回答

14
JavaScript有一个Proxy对象,可以在对象执行操作时设置traps。数组也是对象,可以与代理一起使用。
调用数组的push方法时,新值将被set到数组中。因此,为set方法设置陷阱应该允许我们向push方法添加行为。
在陷阱中,创建一个CustomEvent事件并分派它。您可以随意命名此事件。每当将值添加到dataLayer数组中时,都会发出事件。您可以从每个文件监听此事件,以便在将值添加到dataLayer数组时采取行动。
使用Reflect,我们可以确保恢复push方法的原始行为,同时保留添加的行为。

window.dataLayer = window.dataLayer || new Proxy([], {
  set: (obj, prop, value) => {  
    if (prop !== 'length') {
      const pushEvent = new CustomEvent('datalayerpush', {
        detail: value
      });

      window.dispatchEvent(pushEvent);
    }
    
    return Reflect.set(obj, prop, value);
  }
});

window.addEventListener('datalayerpush', event => {
  console.log(`Value pushed to dataLayer: ${JSON.stringify(event.detail, null, 2)}`);
});

window.dataLayer.push({
  event: 'test'
});


2
为了更明确地替换全局变量中现有的dataLayer引用,如果此代码片段未放置在全局范围内,则最好将其分配给window.dataLayer而不是var dataLayer - jpierson
请记住,这不适用于IE11,但谁在乎已经死亡的浏览器呢;-) - Benedikt

2

我不确定您是否可以使用google_tag_manager对象进行'本地'实现。但是,您可以覆盖dataLayer数组上的push方法。

const originalPush = dataLayer.push
dataLayer.push = function(...args) {
    // notify here
    console.log('dataLayer.push was called');
    
    originalPush(...args);
}

您可以根据观察者模式实现一些逻辑。

以下是非常简单的实现示例,仅供演示。

const originalPush = dataLayer.push
const dataLayerListeners = [];
dataLayer.push = function(...args) {
    dataLayerListeners.forEach(listener => listener.notify())
    
    originalPush(...args);
}

class DatalayerListener {
    constructor(name) {
        this.name = name;
    }
    notify(args) {
        console.log("I'm listener "+this.name+" and I'm being notified that the dataLayer.push method was called");
    }
}

const listener1 = new DatalayerListener('listener1');
const listener2 = new DatalayerListener('listener2');

dataLayerListeners.push(listener1);
dataLayerListeners.push(listener2);

1
我有完全相同的需求,但我也不允许直接修改dataLayer定义,因此无法使用代理。幸运的是,Google创建了一个库,提供了一组针对该对象量身定制的辅助函数:https://github.com/google/data-layer-helper 部署脚本,然后创建回调监听器:
function listener(model, message) {
  // Message has been pushed. 
  // The helper has merged it onto the model.
  // Now use the message and the updated model to do something.
}

这里的额外好处是您可以使用“listenToPast”来重放在代码运行之前添加到dataLayer的所有事件(这也是我情况下的要求)。
const helper = new DataLayerHelper(dataLayer, {
  listener: listener,
  listenToPast: true,
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接