从跨域向父域发送 gtag 事件

Send gtag event from cross domain to parent domain

我正在尝试从起源于我的域并放置在其他域(不是我的)的 iframe 设置一个 send event。我将分析代码放在 iframe.

<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX-XX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-XXXXXXXX-XX',{ 'anonymize_ip': true });
</script>

分析代码(使用 parentdomain.com 中的 UA-XXXXXXXX-XX),我检查一下 iframe 是否不在 我的 parentdomain.com 然后,我将 tracker 属性设置为 div id ads_close:

<script>
ref = document.referrer;
whitelist = ["parentdomain.com"];
match = false;

for( var i = whitelist.length - 1; i >= 0; i-- ) {

 if( ref.indexOf( whitelist[ i ] ) > -1 ) { match = true; }

}
// If is not the parent domain, then add the onClick atributte to the ID "ads_close"
if( ! match ) {

  refer = document.referrer;
  var str1 ="gtag(\'event\', \'External\', {\'event_category\': \'yes\',\'event_label\': ";
  var str2 = "'";  
  var str3 = refer;
  var str4 = "'";
  var str5 = "});";
  var tracker = str1.concat(str2) + str3 + str4 + str5;
ads_close.setAttribute("onClick", tracker);

 }
</script>

以上代码以这种方式呈现,如果不是,在 parentdomain.com:

<div class="adspop_close" id="adspop_close" onclick="gtag('event', 'Externos', {'event_category': 'yes','event_label': 'https://www.theotherdomain.com/post/'});"></div>

问题:

每次我点击 ID 为 adspop_close 的 div,我都无法在我的 parentdomain.com google 分析账户...

问题:

我做错了什么?

如果您尝试从 iframe 本身跟踪数据,它看起来就像交互发生在另一个会话的另一个域上,我认为您正试图避免这种情况。如果您想跟踪 iframe 中的交互并将它们视为父容器的一部分,那么最好的方法是使用 postMessage 将事件传达给父容器,在父容器中可以自然地处理事件。出于安全原因,包含页面没有对 iframe 的脚本访问权限,但 iframe 可以通过 postMessage 向包含页面发送通信。

解决方案 1

Google Development Guide 向我们展示了这种跨域交互的方法(向下滚动到 IFRAME 部分)。

为了 link 在同一个会话中进行交互,您需要共享客户端 ID。不幸的是,iframe 通常会在 google 跟踪准备好客户端 ID 之前很久就使用页面的 HTML 进行初始化。所以我们不能只在加载时传递它,而是需要等待一切,然后使用 postMessage。

这是包含页面的代​​码示例:

<iframe id="destination-frame" src="https://destination.com"></iframe>

<script>
ga('create', 'UA-XXXXX-Y', 'auto');
ga(function(tracker) {
  // Gets the client ID of the default tracker.
  var clientId = tracker.get('clientId');

  // Gets a reference to the window object of the destionation iframe.
  var frameWindow = document.getElementById('destination-frame').contentWindow;

  // Sends the client ID to the window inside the destination frame.
  frameWindow.postMessage(clientId, 'https://destination.com');
});
</script>

这是 iframe 中的侦听器:

window.addEventListener('message', function(event) {
  // Ignores messages from untrusted domains.
  if (event.origin != 'https://destination.com') return;

  ga('create', 'UA-XXXXX-Y', 'auto', {
    clientId: event.data
  });
});

该页面还有一些额外的逻辑来处理客户端 ID 永远不会通过 postMessage 出现的情况。如果您还需要传递 'UA' 字符串并等待完全初始化 iframe 中的 gtag,这也是可行的。收到所需数据后,初始化 gtag 并跟踪。您不需要重写任何 DOM.

解决方案 2

您可以反转 postMessage 通信的逻辑。您根本不需要在 iframe 中进行任何跟踪,而是可以设置任何事件来触发 postMessage,将类别、操作和标签等信息传递到包含页面。在包含页面中,您将为 postMessage 添加侦听器并通过触发 gtag 事件来处理它。

例如,来自 iframe:

<script>
  try {
    var postObject = JSON.stringify({
      event: 'iframeClickEvent', 
      category: 'someCategory',
      action: 'someAction',
      label: 'someLabel'
    });
    parent.postMessage(postObject, 'https://www.YOURWEBSITE.com');
  } catch(e) {
    window.console && window.console.log(e);
  }
</script>

和包含页面:

window.addEventListener('message', function(message) {
  try{
    var data = JSON.parse(message.data);
    var dataLayer = window.dataLayer || (window.dataLayer = []);
    if (data.event === 'iframeClickEvent') {
      dataLayer.push({ 'event': 'someEvent', .... });
    }
  } catch(e){}
});