Search code examples
google-chromegoogle-analyticsgoogle-tag-managercontent-security-policyvue-ssr

GTM nonce-aware script does not work on all browsers for Custom HTML tags


I have a Vue application that uses SSR. In order to implement Content-Security-Policy, I use nonce-aware version of GTM snippet.

But it was not adding the nonce to all scripts that get injected by gtm to the page (specifically Custom HTML tags). I followed the solution mentioned here and it fixed the issue on Safari. But it doesn't work on Chrome, Firefox, or Edge and I still see the error for those tags:

enter image description here

this is my CSP settings:

default-src 'self';
base-uri 'self';
block-all-mixed-content;
font-src 'self' https: https://fonts.gstatic.com data:;
img-src 'self' https: data: https://www.google-analytics.com https://ssl.gstatic.com  https://www.gstatic.com https://www.googletagmanager.com;
object-src 'none';
script-src 'self' 'nonce-b62382357618aee340fc9dc596c94a19' https://www.google-analytics.com/ https://ssl.google-analytics.com https://tagmanager.google.com https://www.googletagmanager.com 127.0.0.1:*;
script-src-attr 'none';
style-src 'self' 'unsafe-inline' https://tagmanager.google.com https://fonts.googleapis.com;
upgrade-insecure-requests;
connect-src 'self' https://www.google-analytics.com https://stats.g.doubleclick.net;

After hours and hours of research I found the following comment:

Chrome masks the nonce attribute value so tag manager is unable to grab it and store it as a variable.

I am not sure if this is really the issue but can anyone please explain how I can tackle this issue without using unsafe-inline or hashes as it seems there is no standard way of fixing it even on Google documentations?


Solution

  • After searching a lot on the internet and reading different articles, I found out the solution mentioned here works perfectly well in Safari but not in other browsers because:

    Chrome, Safari, and Edge mask the nonce attribute value so GTM is unable to grab it and store it as a variable.

    Considering this solution for propagating the nonce to the custom HTML tags, we go ahead and apply the following changes to fix this issue on Chrome, Firefox, and Edge. As suggested here in the comments we need to modify the nonce-aware script a little bit and put the nonce in a data- attribute (then the browsers won't mask it), and push it to the dataLayer:

    <!-- Google Tag Manager -->
    <script
      nonce='{{YOUR_GTM_NONCE}}'
      data-gtm-nonce='{{YOUR_GTM_NONCE}}'
    >
      (function(w,d,s,l,i){
        const gtmNonce = d.querySelector('[data-gtm-nonce]').dataset.gtmNonce;
        w[l]=w[l]||[];
        w[l].push({'nonce': gtmNonce});
        w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});
        const f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';
        j.async=true;
        j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
        j.setAttribute('nonce', gtmNonce);
        f.parentNode.insertBefore(j,f);
      })(window,document,'script','dataLayer','YOUR_GTM_ID');
    </script>
    <!-- End Google Tag Manager -->
    

    Then in the GTM, you need to change the nonce variable you defined based on this solution from this: enter image description here

    to this: enter image description here

    The rest will be kept the same.