How to set the Google Analytics cookie only after another consent cookie is set and "true"?

How to set the Google Analytics cookie only after another consent cookie is set and "true"?

问题

I am using React/Nextjs for my website and the react-cookie-consent library. It creates a pop up where the user can agree to the cookie policy. If agreed, a cookie is set: CookieConsent with value "true".

Additionally, I want to use Google Analytics to track users if they agree (click Accept on the popup).

But it doesnt work: The Google Analytic cookies _ga and G_ENABLED_IDPS are set before the user clicks on the pop up.

Funny thing is, I only realized that on the Microsoft Edge Browser. In Chrome, these cookies are not set before the user gives consent.

This is my current code in _document.js:

<Head>
          {/* Global Site Tag (gtag.js) - Google Analytics */}
          <script
            async
            src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
          />
          <script
            dangerouslySetInnerHTML={{
              __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}            
            gtag('js', new Date());
            
          `}}
          />
          
          <script type="text/javascript" src="/static/blockReactDevTools.js" />
          
          <link href="https://fonts.googleapis.com/css?family=Cabin&display=swap" rel="stylesheet" />

</Head>

I  played around using some hints from the internet, and came up with this version which also doesn't work:

<Head>
          {/* Global Site Tag (gtag.js) - Google Analytics */}
          <script 
            async
            src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
          />

          <script        
            dangerouslySetInnerHTML={{
                __html: `
              
              var gtagId = '${GA_TRACKING_ID}';

              window['ga-disable-' + gtagId] = true;

              window.dataLayer = window.dataLayer || [];

              function gtag(){dataLayer.push(arguments);}   

              gtag('js', new Date());

              function getCookie(cname) {
                var name = cname + "=";
                var ca = document.cookie.split(';');
                for(var i = 0; i < ca.length; i++) {
                  var c = ca[i];
                  while (c.charAt(0) == ' ') {
                    c = c.substring(1);
                  }
                  if (c.indexOf(name) == 0) {
                    return c.substring(name.length, c.length);
                  }
                }
                return "";
              }

              window.addEventListener("load", function() {
                var isCookieConsentTrue = getCookie("CookieConsent") == 'true';

                if(isCookieConsentTrue){
                    window['ga-disable-' + gtagId] = false;
                    alert("Cookie Consent given!");
                    
                  }  else {
                    alert("Cookie Consent NOT given!");
                    window['ga-disable-' + gtagId] = true;
                  }
              });          
            
            `}}
          />

          <script type="text/javascript" src="/static/blockReactDevTools.js" />

          
          <link href="https://fonts.googleapis.com/css?family=Cabin&display=swap" rel="stylesheet" />

</Head>

I don't know if this is a nextjs specific issue, or something plain stupid general.

Can anyone guide me to a working solution?

EDIT: I tried the "Universal Analytics" approach of the suggestion. Suggested Solution make my helper functions to log events and pageviews fail (see below). Do I need also the gtag manager?

 

回答1

The way you were doing it is Opt-out. The GA cookie is always set, as soon as the client requests the gtag.js. This however doesn't comply with GDPR. What you should look into is Opt-in, so that no GA cookie is set without consenting.

The general idea is to async load the gtag.js once the client has consented. For full functionality of gtag functions you have to load the gtag.js on every page-load if the client already consented. Best practice to do this is with a cookieconsent cookie set on consent. There's a widely used js library for this, which generates a popup and sets the consent-cookie for you.

Reference:
https://www.osano.com/cookieconsent/documentation/javascript-api/
You can generate code for the layout of your cookie banner by clicking Start Coding here: https://www.osano.com/cookieconsent/download/ https://github.com/osano/cookieconsent/blob/dev/examples/example-7-javascript-api.html

Following code has to be implemented on every page in the <head> section:

<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.1/cookieconsent.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.1/cookieconsent.min.js" data-cfasync="false"></script>
<script>
var popup;
window.addEventListener('load', function(){
  window.cookieconsent.initialise({
   //set revokeBtn if you don't want to see a tiny pullup bar overlapping your website
   //if revokeBtn is set, make sure to include a link to cookie settings in your footer
   //you can open your banner again with: popup.open();
   //revokeBtn: "<div class='cc-revoke'></div>",
   type: "opt-in",
   theme: "classic",
   palette: {
       popup: {
           background: "#000",
           text: "#fff"
        },
       button: {
           background: "#fd0",
           text: "#000"
        }
    },
    onInitialise: function(status) {
      // request gtag.js on page-load when the client already consented
      if(status == cookieconsent.status.allow) setCookies();
    },
    onStatusChange: function(status) {
      // resquest gtag cookies on a new consent
      if (this.hasConsented()) setCookies();
      else deleteCookies(this.options.cookie.name)
    },
/* enable this to hide the cookie banner outside GDPR regions
    law: {
      regionalLaw: false,
    },
    location: true,
    },
*/
    function (p) {
        popup = p;
  })
});

//it is absolutely crucial to define gtag in the global scope
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_TRACKING_ID}', {'anonymize_ip': true});

function setCookies() {
    var s = document.createElement('script');
    s.type = "text/javascript"
    s.async = "true";
    s.src = "https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}";
    var x = document.getElementsByTagName('script')[0];
    x.parentNode.insertBefore(s, x);

    // you can add facebook-pixel and other cookies here
};

function deleteCookies(cookieconsent_name) {
        var keep = [cookieconsent_name, "DYNSRV"];

        document.cookie.split(';').forEach(function(c) {
            c = c.split('=')[0].trim();
            if (!~keep.indexOf(c))
                document.cookie = c + '=;' + 'expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/';
        });
};
</script>

Note:
Make sure that the gtag.js is loaded on every page-load once the consent-cookie was set to allow. Use event_callback to see if a gtag event was sent. You can use the gtag function without checking for the consent-cookie. If gtag.js is not present it just adds elements to the window.dataLayer without any functionality. To avoid errors, the function gtag() has to be declared in global scope and before use.

// cookie-check is not necessary when gtag is in global scope
//if(popup.hasConsented()) { 
    gtag('event', 'sign_up', {
            'method': 'Google',
            'event_callback': function(){alert('event was sent');}
        });
//}

You don't have to send an extra pageview event, unless you want to manually specify the path. setCookies() already sends the current document path along with the config

 

回答2

Use gtag's consent config options. Currently, the following can be put before any data measurement commands (config or event) are run in the header:

gtag('consent', 'default', {
  'ad_storage': 'denied',
  'analytics_storage': 'denied'
});

Then run this once the user has approved or if a consent cookie is present:

gtag('consent', 'update', {
  'ad_storage': 'granted',
  'analytics_storage': 'granted'
});

If you use Facebook Pixel, it works in a similar way. E.g. fbq('consent', 'revoke'); then fbq('consent', 'grant').

 

Github搜索,两个repository用到相似的代码

主体代码应该是参考这个https://www.cnblogs.com/chucklu/p/16497448.html

 

https://github.com/lixiaomeng546/hongye/blob/7bc6d5ddcdca220c7a1976b3116504a8f130b2c6/game/game3.html

<!-- Google Analytics -->
<script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}

    gtag('set', 'developer_id.dNzMyY2', true); // OneTrust developer id
    gtag('consent', 'default', {
        'analytics_storage': 'denied',
        'ad_storage': 'denied',
        'wait_for_update': 1000
    });

    gtag('js', new Date());

    if (window.navigator.standalone) {
        gtag('set', {
          'dimension1': true
        });
    }

    gtag('config', "UA-23605814-1");

    if (!window._optanonCallbacks) {
        window._optanonCallbacks = [];
    }

    _optanonCallbacks.push(function () {
        // if consent given for cookies then
        // update gtag consent
        var analytics = (OnetrustActiveGroups.indexOf('C0002') != -1);
        var ads = (OnetrustActiveGroups.indexOf('C0004') != -1);
        if (analytics || ads) {
            gtag('consent', 'update', {
                'analytics_storage': analytics ? 'granted' : 'denied',
                'ad_storage': ads ? 'granted' : 'denied'
            });
        }
    });

</script>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-23605814-1"></script>
<!-- End Google Analytics -->

 

https://github.com/nightsky108/developcanvas.com/blob/01d52275bb7695745418a0e6dce195acbca6179a/templates/partials/analytics.tmpl.html

{{#if prod}}
<script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}

    gtag('set', 'developer_id.dNzMyY2', true); // OneTrust developer id
    gtag('consent', 'default', {
        'analytics_storage': 'denied',
        'ad_storage': 'denied',
        'wait_for_update': 1000
    });

    // Google Analytics
    gtag('js', new Date());

    gtag('config', 'UA-23605814-1');

    if (!window._optanonCallbacks) {
        window._optanonCallbacks = [];
    }

    _optanonCallbacks.push(function () {
        // if consent given for cookies then
        // update gtag consent
        var analytics = (OnetrustActiveGroups.indexOf('C0002') != -1);
        var ads = (OnetrustActiveGroups.indexOf('C0004') != -1);
        if (analytics || ads) {
            gtag('consent', 'update', {
                'analytics_storage': analytics ? 'granted' : 'denied',
                'ad_storage': ads ? 'granted' : 'denied'
            });
        }
    });
</script>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-23605814-1"></script>
<script src="https://playcanvas.com/static/platform/js/onetrust/consent.js"></script>
{{/if}}

 

作者:Chuck Lu    GitHub    
posted @   ChuckLu  阅读(206)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2020-07-19 IIS自带的http modules分别注册了HttpApplication pipeline里面的哪些事件
2019-07-19 .NET Assembly File Format
2019-07-19 dnSpy PE format ( Portable Executable File Format)
2019-07-19 .net 查壳工具
2019-07-19 How to change the button text of <input type=“file” />?
点击右上角即可分享
微信分享提示