CSP and GA/GTM

Tuesday, December 3, 2024
5 min read
Theotime QuereTheotime Quere
Implementing Google Analytics (GA) or Google Tag Manager (GTM) while maintaining a strict Content Security Policy can be challenging. This guide will walk you through the process of setting up both services securely with CSP.

Setting up Google Analytics with CSP

How Google Analytics Works

Google Analytics works by loading several scripts and making requests to Google's servers to track user behavior. The main challenges when implementing GA with CSP are:
  • Loading the initial analytics.js or gtag.js script
  • Allowing connections to Google's data collection endpoints
  • Handling dynamically injected scripts and inline scripts

Using Nonce or Hashes

There are two approaches to allow Google Analytics scripts with CSP:
  • Using nonces (recommended)
  • Using hashes (requires more maintenance)
Learn more about implementing nonces

CSP Configuration for Google Analytics

Basic CSP configuration for Google Analytics

Content-Security-Policy: 
script-src 'nonce-{random_nonce}' 'strict-dynamic' https://www.googletagmanager.com https://www.google-analytics.com;
connect-src https://www.google-analytics.com https://analytics.google.com;
img-src https://www.google-analytics.com;

Monitoring

Enable CSP reporting to monitor any blocked resources. This will help you identify any missing directives needed for Google Analytics.

Setting up Google Tag Manager with CSP

Understanding Google Tag Manager

Google Tag Manager is more complex than GA because it can dynamically load various scripts and tags. This requires a different approach to CSP configuration.

Why Nonce is Mandatory for GTM

Using nonces with 'strict-dynamic' is the recommended approach for GTM because:
  • It automatically trusts scripts loaded by trusted (nonced) scripts
  • Eliminates the need to maintain hash lists
  • Handles dynamically injected scripts properly

CSP Configuration for Google Tag Manager

Basic CSP configuration for Google Tag Manager

Content-Security-Policy: 
  script-src 'nonce-{random_nonce}';
  img-src www.googletagmanager.com;
  connect-src www.googletagmanager.com;

Implementing GTM with Nonce

Here's how to implement GTM in a Next.js application:

Implementing GTM with Nonce, use this script in your layout after getting the nonce (server side)

<script nonce={nonce} dangerouslySetInnerHTML={{
      __html: `(function(w,d,s,l,i){
          w[l]=w[l]||[];
          w[l].push({
              'gtm.start': new Date().getTime(),
              event:'gtm.js'
          });
          var 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;
          f.parentNode.insertBefore(j,f);
      })(window,document,'script','dataLayer','GTM-XXXXXX');`
  }} />

Global Variables

Warning: Avoid using global variables in GTM scripts, as this may require 'unsafe-eval' in your CSP.

Monitoring

Enable CSP reporting to monitor any blocked resources. This will help you identify any missing directives needed for Google Analytics.

Full Example with Nonce Implementation

Here's a complete example combining both GA and GTM:

Full Example with Nonce Implementation

Content-Security-Policy: 
  default-src 'self';
  script-src 'nonce-${nonce}' 'strict-dynamic';
  connect-src https://*.google-analytics.com https://*.analytics.google.com https://*.googletagmanager.com;
  img-src https://*.google-analytics.com https://*.googletagmanager.com;
  frame-src https://*.google.com;
  style-src 'self' 'unsafe-inline';

Conclusion

Implementing Google Analytics and Google Tag Manager with CSP requires careful configuration, but using nonces with 'strict-dynamic' provides the best balance of security and functionality. Remember to:

  • Always use CSP reporting to monitor for blocked resources
  • Implement nonce generation and rotation
  • Avoid using global variables in GTM scripts
  • Regularly review and update your CSP configuration