在页面加载之后通过在head中添加脚本加载谷歌分析并不总是有效的

时间:2022-07-28 15:18:58

In the EU, there's a cookie law that requires you to load third-party scripts after the user expresses consent, by clicking, scrolling or navigating for instance. So I load 3 scripts by executing a function that's called after document loads. This is the code:

在欧盟,有一项cookie法律要求你在用户表示同意后加载第三方脚本,比如点击、滚动或导航。我通过执行一个在文档加载之后调用的函数来加载3个脚本。这是代码:

在页面加载之后通过在head中添加脚本加载谷歌分析并不总是有效的

The problem is that it doesn't always work, nor always fail. I see sessions and activity but I also know for a fact that there are visits that don't trigger the scripts because when I tested it myself on several other computers, not all activity was saved in analytics.

问题是它并不总是有效,也不总是失败。我看到了会话和活动,但我也知道有一些访问不会触发脚本,因为当我在其他几台计算机上测试它时,并不是所有的活动都保存在分析中。

What should I fix in the function to make it work all the time?

为了让函数一直工作,我应该在函数中设置什么?

8 个解决方案

#1


10  

$(document).ajaxComplete(function() {
        var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'UA-XXXXX-X']);
      _gaq.push(['_trackPageview']);

       var loadGoogleAnalytics = function(){
         var ga = document.createElement('script');
           ga.type = 'text/javascript';
           ga.async = true;
           ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

           var s = document.getElementsByTagName('script')[0];
           s.parentNode.insertBefore(ga, s);
        }
    });

#2


4  

You can try use this function that works fine to me:

你可以尝试使用这个对我来说很有用的功能:

function loadGoogleAnalytics(trackingId) {
                var deferred = $q.defer();

                function loadScript() {
                    var scriptId = 'google-analytics';

                    if (document.getElementById(scriptId)) {
                        deferred.resolve();
                        return;
                    }

                    var s = document.createElement('script');
                    s.id = scriptId;
                    s.innerText = "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');ga('create', '" + trackingId + "', 'auto');";

                    // most browsers
                    s.onload = initGA();
                    // IE 6 & 7
                    s.onreadystatechange = function () {
                        if (this.readyState == 'complete') {
                            initGA();
                        }
                    }

                    document.getElementsByTagName('head')[0].appendChild(s);
                }

                $window.initGA = function () {
                    deferred.resolve();
                }

                loadScript();

                return deferred.promise;
            }

#3


4  

If you have a look at this post, you can modify it slightly to achieve what you want:

如果你看过这篇文章,你可以稍微修改一下,以达到你想要的效果:

<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXX-X']);
  _gaq.push(['_trackPageview']);

   var loadGoogleAnalytics = function(){
     var ga = document.createElement('script');
       ga.type = 'text/javascript';
       ga.async = true;
       ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

       var s = document.getElementsByTagName('script')[0];
       s.parentNode.insertBefore(ga, s);
    }
</script>

Then just call loadGoogleAnalytics() whenever the user agrees with your Cookie Usage display

然后,只要用户同意您的Cookie使用显示,就调用loadGoogleAnalytics()

#4


4  

Other response seems to be targeting ga.js which is legacy, whereas your question seems to be oriented towards analytics.js (current).

其他的回应似乎是针对ga。js是遗产,而你的问题似乎是针对分析的。js(当前)。

Studying the analytics.js snippet a little you can easily find an answer (below, formatted with prettier):

研究分析。你可以很容易地找到答案(如下,格式更漂亮):

(function(i, s, o, g, r, a, m) {
  i["GoogleAnalyticsObject"] = r;
  (i[r] =
    i[r] ||
    function() {
      (i[r].q = i[r].q || []).push(arguments);
    }), (i[r].l = 1 * new Date());
  (a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
  a.async = 1;
  a.src = g;
  m.parentNode.insertBefore(a, m);
})(
  window,
  document,
  "script",
  "https://www.google-analytics.com/analytics.js",
  "ga"
);

ga("create", "UA-XXXXX-Y", "auto");
ga("send", "pageview");

The trick is easy : Google creates a global var GoogleAnalyticsObject which is a string representing the name of the global GoogleAnalytics. You can see that by default it's "ga".

诀窍很简单:谷歌创建一个全局var GoogleAnalyticsObject,它是表示全局GoogleAnalytics名称的字符串。你可以看到默认情况下它是“ga”。

So, at loading you need to create two global vars : GoogleAnalyticsObject which is a string and window[GoogleAnalyticsObject] which is the function ( which just accumulates events, this function is replaced when the lib is loaded I guess ). Then when your user accepts the cookies you can load the lib and you're done :)

因此,在加载时,您需要创建两个全局vars: GoogleAnalyticsObject,它是一个字符串,而window[GoogleAnalyticsObject]是一个函数(它只是积累事件,我猜这个函数在加载lib时被替换)。然后,当用户接受cookie时,您就可以加载lib并完成:)

#5


4  

Could you try adding the following instead of a call to .innerHTML()

是否可以尝试添加以下内容,而不是调用.innerHTML()

//...text above...
TheAnalyticsScript.text = ['ga-script-string', 'fb-script.string','hotjar.string'].join('\n');
$('body').append(TheAnalyticsScript);

Please let me know if that works.

如果可以的话,请告诉我。

#6


3  

Here's my pick on the problem. The solution simply patches the default scripts to return function which then adds the script tag only after the consent is granted. Have a look:

这是我对这个问题的看法。该解决方案只是将默认脚本补丁为返回函数,然后在同意之后添加脚本标记。看一看:

// for GoogleAnalytics
var loadGA = (function(i, s, o, g, r, a, m) {
  i['GoogleAnalyticsObject'] = r;
  i[r] = i[r] || function() {
      (i[r].q = i[r].q || []).push(arguments)
    },
    i[r].l = 1 * new Date();

  // call this function after receiving consent
  return function loadGA() {
    a = s.createElement(o),
      m = s.getElementsByTagName(o)[0];
    a.async = 1;
    a.src = g;
    m.parentNode.insertBefore(a, m)
  }
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');

// for Facebook
window.fbAsyncInit = function() {
  FB.init({
    appId: 'your-app-id',
    autoLogAppEvents: true,
    xfbml: true,
    version: 'v2.10'
  });
  FB.AppEvents.logPageView();
};

var loadFB = (function(d, s, id) {
  //- call this function after receiving consent
  return function loadFB() {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) {
      return;
    }
    js = d.createElement(s);
    js.id = id;
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
  }
}(document, 'script', 'facebook-jssdk'));

// for HotJar
var loadHJ = (function(h, o, t, j, a, r) {
  h.hj = h.hj || function() {
    (h.hj.q = h.hj.q || []).push(arguments)
  };
  h._hjSettings = {
    hjid: 1,
    hjsv: 5
  };

  return function loadHJ() {
    a = o.getElementsByTagName('head')[0];
    r = o.createElement('script');
    r.async = 1;
    r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv;
    a.appendChild(r);
  }
})(window, document, '//static.hotjar.com/c/hotjar-', '.js?sv=');

// finally when you receive the consent
function onConsentReceived() {
  loadGA();
  loadFB();
  loadHJ();
}

//- meanwhile you can continue using ga(), hj() whatever here...

Each of the loader can be in it's own script tag but make sure about the ordering of those tags.

每个加载程序都可以在自己的脚本标记中,但是要确保这些标记的顺序。

#7


0  

Thinking about what your code does, this function:

考虑你的代码做什么,这个函数:

  1. Creates a <script> element filled with strings
  2. 创建一个包含字符串的
  3. Adds it to the <head>
  4. 将其添加到。

Note that the <head> is afaik supposed to be loaded only at the initial load. Depending on the browser implementation etc it might be the case that some of your visitor's browsers ignore the <script> tag you add after the page load is completed.

注意,是afaik,应该只在初始负载时加载。根据浏览器实现等的不同,您的一些访问者的浏览器可能会忽略在页面加载完成后添加的

If I understand when you want to do right you want:

如果我理解你想要做对的事,你想:

  1. To load the page without the tracking scripts
  2. 在没有跟踪脚本的情况下加载页面
  3. Show a consent modal/popup
  4. 显示一个模态同意/弹出
  5. On 'agree' click trigger this function without a page reload
  6. 在“同意”点击触发这个功能,没有页面重新加载。

note: many EU websites reload the page after cookie consent because they add the <script> tags with tracking to the page using backend rendering. Often clicking 'I agree to cookies' they store a agreed: true type cookie that changes what webpage their server sends.

注意:许多欧盟网站在获得cookie同意后重新加载页面,因为他们使用后端呈现将

If you don't care about reloads:

  1. Set a cookie when the user agrees
  2. 当用户同意时设置一个cookie
  3. Reload the page
  4. 重新加载页面
  5. Have your backend (php/node/ruby/whatever) add a script tag based on this cookie
  6. 您的后端(php/node/ruby/随便什么)是否添加了基于此cookie的脚本标记

If you do care

Change your function to run the tracking codes instead of adding them to the DOM.

更改您的函数来运行跟踪代码,而不是将它们添加到DOM中。

Just look at the tracking codes and break them down into easy to read code. For example the Ga code is actually simply:

只需查看跟踪代码并将其分解为易于阅读的代码。例如,Ga代码实际上很简单:

var ga = document.createElement('script')
ga.type = 'text/javascript'
ga.async = true
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);

And then

然后

function addTrackers() {

// Execute the tracking things instead of adding them to the DOM

}

#8


0  

Rather than appending the entire analytics script, you could have it included always but remove the following line:

与其添加整个分析脚本,还可以将它包括在内,但要删除以下一行:

ga("send", "pageview");

Then, when the user accepts the cookies.. fire the analytics function that sends the beacon using that same line above. Analytics does not actually send any data unless being told to specifically. That would be the most logical way of doing what you are attempting.

然后,当用户接受cookie。使用上面的同一行启动发送信标的分析功能。分析实际上并没有发送任何数据,除非被明确告知。那将是最符合逻辑的方式去做你想做的事。

#1


10  

$(document).ajaxComplete(function() {
        var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'UA-XXXXX-X']);
      _gaq.push(['_trackPageview']);

       var loadGoogleAnalytics = function(){
         var ga = document.createElement('script');
           ga.type = 'text/javascript';
           ga.async = true;
           ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

           var s = document.getElementsByTagName('script')[0];
           s.parentNode.insertBefore(ga, s);
        }
    });

#2


4  

You can try use this function that works fine to me:

你可以尝试使用这个对我来说很有用的功能:

function loadGoogleAnalytics(trackingId) {
                var deferred = $q.defer();

                function loadScript() {
                    var scriptId = 'google-analytics';

                    if (document.getElementById(scriptId)) {
                        deferred.resolve();
                        return;
                    }

                    var s = document.createElement('script');
                    s.id = scriptId;
                    s.innerText = "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');ga('create', '" + trackingId + "', 'auto');";

                    // most browsers
                    s.onload = initGA();
                    // IE 6 & 7
                    s.onreadystatechange = function () {
                        if (this.readyState == 'complete') {
                            initGA();
                        }
                    }

                    document.getElementsByTagName('head')[0].appendChild(s);
                }

                $window.initGA = function () {
                    deferred.resolve();
                }

                loadScript();

                return deferred.promise;
            }

#3


4  

If you have a look at this post, you can modify it slightly to achieve what you want:

如果你看过这篇文章,你可以稍微修改一下,以达到你想要的效果:

<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXX-X']);
  _gaq.push(['_trackPageview']);

   var loadGoogleAnalytics = function(){
     var ga = document.createElement('script');
       ga.type = 'text/javascript';
       ga.async = true;
       ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

       var s = document.getElementsByTagName('script')[0];
       s.parentNode.insertBefore(ga, s);
    }
</script>

Then just call loadGoogleAnalytics() whenever the user agrees with your Cookie Usage display

然后,只要用户同意您的Cookie使用显示,就调用loadGoogleAnalytics()

#4


4  

Other response seems to be targeting ga.js which is legacy, whereas your question seems to be oriented towards analytics.js (current).

其他的回应似乎是针对ga。js是遗产,而你的问题似乎是针对分析的。js(当前)。

Studying the analytics.js snippet a little you can easily find an answer (below, formatted with prettier):

研究分析。你可以很容易地找到答案(如下,格式更漂亮):

(function(i, s, o, g, r, a, m) {
  i["GoogleAnalyticsObject"] = r;
  (i[r] =
    i[r] ||
    function() {
      (i[r].q = i[r].q || []).push(arguments);
    }), (i[r].l = 1 * new Date());
  (a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
  a.async = 1;
  a.src = g;
  m.parentNode.insertBefore(a, m);
})(
  window,
  document,
  "script",
  "https://www.google-analytics.com/analytics.js",
  "ga"
);

ga("create", "UA-XXXXX-Y", "auto");
ga("send", "pageview");

The trick is easy : Google creates a global var GoogleAnalyticsObject which is a string representing the name of the global GoogleAnalytics. You can see that by default it's "ga".

诀窍很简单:谷歌创建一个全局var GoogleAnalyticsObject,它是表示全局GoogleAnalytics名称的字符串。你可以看到默认情况下它是“ga”。

So, at loading you need to create two global vars : GoogleAnalyticsObject which is a string and window[GoogleAnalyticsObject] which is the function ( which just accumulates events, this function is replaced when the lib is loaded I guess ). Then when your user accepts the cookies you can load the lib and you're done :)

因此,在加载时,您需要创建两个全局vars: GoogleAnalyticsObject,它是一个字符串,而window[GoogleAnalyticsObject]是一个函数(它只是积累事件,我猜这个函数在加载lib时被替换)。然后,当用户接受cookie时,您就可以加载lib并完成:)

#5


4  

Could you try adding the following instead of a call to .innerHTML()

是否可以尝试添加以下内容,而不是调用.innerHTML()

//...text above...
TheAnalyticsScript.text = ['ga-script-string', 'fb-script.string','hotjar.string'].join('\n');
$('body').append(TheAnalyticsScript);

Please let me know if that works.

如果可以的话,请告诉我。

#6


3  

Here's my pick on the problem. The solution simply patches the default scripts to return function which then adds the script tag only after the consent is granted. Have a look:

这是我对这个问题的看法。该解决方案只是将默认脚本补丁为返回函数,然后在同意之后添加脚本标记。看一看:

// for GoogleAnalytics
var loadGA = (function(i, s, o, g, r, a, m) {
  i['GoogleAnalyticsObject'] = r;
  i[r] = i[r] || function() {
      (i[r].q = i[r].q || []).push(arguments)
    },
    i[r].l = 1 * new Date();

  // call this function after receiving consent
  return function loadGA() {
    a = s.createElement(o),
      m = s.getElementsByTagName(o)[0];
    a.async = 1;
    a.src = g;
    m.parentNode.insertBefore(a, m)
  }
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');

// for Facebook
window.fbAsyncInit = function() {
  FB.init({
    appId: 'your-app-id',
    autoLogAppEvents: true,
    xfbml: true,
    version: 'v2.10'
  });
  FB.AppEvents.logPageView();
};

var loadFB = (function(d, s, id) {
  //- call this function after receiving consent
  return function loadFB() {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) {
      return;
    }
    js = d.createElement(s);
    js.id = id;
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
  }
}(document, 'script', 'facebook-jssdk'));

// for HotJar
var loadHJ = (function(h, o, t, j, a, r) {
  h.hj = h.hj || function() {
    (h.hj.q = h.hj.q || []).push(arguments)
  };
  h._hjSettings = {
    hjid: 1,
    hjsv: 5
  };

  return function loadHJ() {
    a = o.getElementsByTagName('head')[0];
    r = o.createElement('script');
    r.async = 1;
    r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv;
    a.appendChild(r);
  }
})(window, document, '//static.hotjar.com/c/hotjar-', '.js?sv=');

// finally when you receive the consent
function onConsentReceived() {
  loadGA();
  loadFB();
  loadHJ();
}

//- meanwhile you can continue using ga(), hj() whatever here...

Each of the loader can be in it's own script tag but make sure about the ordering of those tags.

每个加载程序都可以在自己的脚本标记中,但是要确保这些标记的顺序。

#7


0  

Thinking about what your code does, this function:

考虑你的代码做什么,这个函数:

  1. Creates a <script> element filled with strings
  2. 创建一个包含字符串的
  3. Adds it to the <head>
  4. 将其添加到。

Note that the <head> is afaik supposed to be loaded only at the initial load. Depending on the browser implementation etc it might be the case that some of your visitor's browsers ignore the <script> tag you add after the page load is completed.

注意,是afaik,应该只在初始负载时加载。根据浏览器实现等的不同,您的一些访问者的浏览器可能会忽略在页面加载完成后添加的

If I understand when you want to do right you want:

如果我理解你想要做对的事,你想:

  1. To load the page without the tracking scripts
  2. 在没有跟踪脚本的情况下加载页面
  3. Show a consent modal/popup
  4. 显示一个模态同意/弹出
  5. On 'agree' click trigger this function without a page reload
  6. 在“同意”点击触发这个功能,没有页面重新加载。

note: many EU websites reload the page after cookie consent because they add the <script> tags with tracking to the page using backend rendering. Often clicking 'I agree to cookies' they store a agreed: true type cookie that changes what webpage their server sends.

注意:许多欧盟网站在获得cookie同意后重新加载页面,因为他们使用后端呈现将

If you don't care about reloads:

  1. Set a cookie when the user agrees
  2. 当用户同意时设置一个cookie
  3. Reload the page
  4. 重新加载页面
  5. Have your backend (php/node/ruby/whatever) add a script tag based on this cookie
  6. 您的后端(php/node/ruby/随便什么)是否添加了基于此cookie的脚本标记

If you do care

Change your function to run the tracking codes instead of adding them to the DOM.

更改您的函数来运行跟踪代码,而不是将它们添加到DOM中。

Just look at the tracking codes and break them down into easy to read code. For example the Ga code is actually simply:

只需查看跟踪代码并将其分解为易于阅读的代码。例如,Ga代码实际上很简单:

var ga = document.createElement('script')
ga.type = 'text/javascript'
ga.async = true
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);

And then

然后

function addTrackers() {

// Execute the tracking things instead of adding them to the DOM

}

#8


0  

Rather than appending the entire analytics script, you could have it included always but remove the following line:

与其添加整个分析脚本,还可以将它包括在内,但要删除以下一行:

ga("send", "pageview");

Then, when the user accepts the cookies.. fire the analytics function that sends the beacon using that same line above. Analytics does not actually send any data unless being told to specifically. That would be the most logical way of doing what you are attempting.

然后,当用户接受cookie。使用上面的同一行启动发送信标的分析功能。分析实际上并没有发送任何数据,除非被明确告知。那将是最符合逻辑的方式去做你想做的事。