Cómo integrar Google Analytics en NextJS para cumplir con la Ley de Protección de Datos
Tags: nextjs, analytics, privacy, spanish
Published: 2021-10-09 20:14:32

## ¿Qué vamos a hacer?

En este post configuraremos Google Analytics en una página web creada con NextJS, teniendo en cuenta la autorización del usuario para la recogida de datos y el uso de cookies.

---

## Requisitos previos

Antes de comenzar con el código, necesitarás tener acceso a los siguientes recursos:

- Archivo [\_document.js](https://nextjs.org/docs/advanced-features/custom-document)
- Archivo [\_app.js](https://nextjs.org/docs/advanced-features/custom-app)

Puedes consultar la [documentación oficial](https://nextjs.org/docs) para saber qué son y cómo configurarlos en tu proyecto.

También deberás tener acceso a una cuenta de [Google analytics](https://analytics.google.com/analytics/web/) y deberás crear un nuevo proyecto de GA y obtener la [ID de seguimiento](https://support.google.com/analytics/answer/7372977).

---

## Configurar Google Analytics en la web

<br />

### Configurando los scripts de Google Analytics

Lo primero que deberemos hacer es configurar los scripts de GA en el archivo `_document.js`. Estos scripts son los que se encargan de configurar la instancia de GA a nivel global en nuestro sitio web. Para ello abrimos el archivo `_document.js` y añadimos las siguientes líneas de código en el elemento `head`:

```js
<script async src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GOOGLE_ANALYTICS}`} />
<script dangerouslySetInnerHTML={{
	__html:`
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}

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

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

		gtag('config', '${process.env.GOOGLE_ANALYTICS}', {
            page_path: window.location.pathname,
        });
        `,
		}} />

```

El archivo final debería quedar similar a esto:

```js
import Document, { Html, Head, Main, NextScript } from "next/document";

class MyDocument extends Document {
	static async getInitialProps(ctx) {
		const initialProps = await Document.getInitialProps(ctx);
		return { ...initialProps };
	}

	render() {
		return (
			<Html>
				<Head>
					<script async src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GOOGLE_ANALYTICS}`} />
					<script
						dangerouslySetInnerHTML={{
							__html:`
            				window.dataLayer = window.dataLayer || [];
            				function gtag(){dataLayer.push(arguments);}

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

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

							gtag('config', '${process.env.GOOGLE_ANALYTICS}', {
								page_path: window.location.pathname,
							});
          					`,
						}}
					/>
				</Head>
				<body>
					<Main />
					<NextScript />
				</body>
			</Html>
		);
	}
}

export default MyDocument;
```

Como ves, estamos utilizando una variable de entorno, que configuraremos más adelante, donde se almacenará el ID de seguimiento de Google Analytics.

Además, para poder detectar los diferentes eventos que ocurren en la página, es necesario añadir las siguientes líneas al archivo `_app.js`:

```js
import { useEffect } from "react";
import { useRouter } from "next/router";

//dentro del componente App
const router = useRouter();

useEffect(() => {
	const handleRouteChange = (url) => {
		window.gtag("config", process.env.GOOGLE_ANALYTICS, {
			page_path: url,
		});
	};
	router.events.on("routeChangeComplete", handleRouteChange);
	return () => {
		router.events.off("routeChangeComplete", handleRouteChange);
	};
}, [router.events]);
```

El archivo final quedará similar a esto:

```js
import "../styles/globals.css";
import { useEffect } from "react";
import { useRouter } from "next/router";

function App({ Component, pageProps }) {
	const router = useRouter();

	useEffect(() => {
		const handleRouteChange = (url) => {
			window.gtag("config", process.env.GOOGLE_ANALYTICS, {
				page_path: url,
			});
		};
		router.events.on("routeChangeComplete", handleRouteChange);
		return () => {
			router.events.off("routeChangeComplete", handleRouteChange);
		};
	}, [router.events]);

	return <Component {...pageProps} />

}

export default App;

```

<br />

### Pidiendo permiso al usuario: renderizado condicional de los scripts de GA.

Con esto ya tenemos Google Analytics funcionando en nuestro sitio web. Pero ahora debemos tener en cuenta que Google Analtics solo debe ser utilizado tras el consentimineto del usuario, por lo que procederemos a añadir los elementos necesarios para pedir ese permiso.

El primer cambio que debemos realizar es **configurar los scripts de analytics para que no se carguen automáticamente**. Para ello volveremos al archivo `_document.js` y añadiremos un condicional a nuestro código:

```js
<script
	dangerouslySetInnerHTML={{
		__html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}

			//configuramos el permiso como denegado en primera instancia
    		gtag('consent', 'default', {
      			'analytics_storage': 'denied'
    		});

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

			//comprobamos el consentimiento
			if( consentimiento ) {
    			gtag('consent', 'update', {
     			'analytics_storage': 'granted'
    			});
  			}

            gtag('config', '${process.env.GOOGLE_ANALYTICS}', {
            	page_path: window.location.pathname,
           	});
        `,
	}}
/>
```

Ahora no se cargan automáticamente los scripts sino que dependerá del consentimiento del usuario.

Es el momento de preguntar al usuario si desea o no que realicemos seguimiento de sus datos. Para ello, podemos utilizar algún componente de React ya existente que nos permita preguntar al usuario y almacenar sus preferencias en una _cookie de preferencias_.

En este caso utilizaremos la librería [react-cookie-consent](https://www.npmjs.com/package/react-cookie-consent).

Podemos instalarla a través de la consola en nuestro proyecto:

```bash
npm install react-cookie-consent

# o utilizando yarn

yarn add react-cookie-consent
```

Una vez instalado debemos añadir el componente de forma global, de manera que, entre donde entre el usuario, se le pregunte por sus preferencias, en caso de no tener un registro previo de las mismas. Este componente se encarga automáticamente de comprobar si ya hay una cookie previa de preferencias por lo que será muy facil implementar el sistema.

Para añadirlo de forma global lo añadimos al componente `App` de nuestra web:

```js
import "../styles/globals.css";
import { useEffect } from "react";
import { useRouter } from "next/router";
import CookieConsent from "react-cookie-consent";

function App({ Component, pageProps }) {
const router = useRouter();

    useEffect(() => {
    	const handleRouteChange = (url) => {
    		window.gtag("config", process.env.GOOGLE_ANALYTICS, {
    			page_path: url,
    		});
    	};
    	router.events.on("routeChangeComplete", handleRouteChange);
    	return () => {
    		router.events.off("routeChangeComplete", handleRouteChange);
    	};
    }, [router.events]);

    return (
    	<>
    		<Component {...pageProps} />
    		<CookieConsent
    		location="bottom"
    		buttonText="Sí, utilizar cookies."
    		onAccept={() => location.reload()}
    		cookieName="CookieConsent"
    		expires={150}
    		enableDeclineButton="true"
    		declineButtonText="No, no utilizar cookies"
    		>
    		Poner aquí el mensaje sobre el uso de cookies
    		<a href="#enlace_hacia_politica_de_cookies">Política de Cookies</a>.
    	</CookieConsent>
    	</>
    );

}

export default App;

```

_Puedes cosultar el repo del componente para configurarlo a tu gusto._

Ya tenemos la capacidad de crear una cookie de preferencias y de preguntarle al usuario qué es lo que quiere. Ahora debemos volver al archivo `_document.js` e introducir la función que nos devuelva el valor de la cookie de preferencias, para saber si debemos cargar el script de rastreo o no.

Añadimos lo siguiente en el archivo `_document.js`:

```js
<script
	dangerouslySetInnerHTML={{
		__html: `
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
		//this defaults to denying
    	gtag('consent', 'default', {
      		'analytics_storage': 'denied'
    	});

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

		//este función es la que nos devuelve el valor de la cookie de preferencias
		function getCookie() {
			const value = "; " + document.cookie;
			const parts = value.split("; CookieConsent=");
			if (parts.length === 2) return parts.pop().split(';').shift();
		}

		//únicamente si el valor es true, se cargan los scripts de Google Analytics.
		if(getCookie() === "true"){
    		gtag('consent', 'update', {
     			'analytics_storage': 'granted'
    		});
  		}

        gtag('config', '${process.env.GOOGLE_ANALYTICS}', {
         	page_path: window.location.pathname,
        });
        `,
	}}
/>
```

Con esto ya tendremos todo funcionando 🚀. Ahora deberás hacer un deploy en Vercel y [configurar la variable de entorno](https://vercel.com/docs/environment-variables) `GOOGLE_ANALYTICS` con el valor del ID de rastreo de tu sitio web.
Tras añadir la variable de entorno deberás de hacer otro despliegue para que estas san tenidas en cuenta en tu sitio web.

<br />

## Código completo

Puedes ver todo el código en el siguiente repositorio:

{% github dubisdev/nextjs-analytics-rgpd %}


---

### Crear una página de Política de Cookies

¡Espera un momento! Todavía queda un paso importante: crear una página donde expliques el uso que se le da a las cookies y las instrucciones para revocar los permisos y/o borrar los datos en caso de ser necesario.

Como idea, puedes echarle un vistazo a la [publicación de la Agencia Estatal de Protección de Datos](https://www.aepd.es/sites/default/files/2020-07/guia-cookies.pdf) para saber qué debe incluir.

<br />

---

## Exención de responsabilidades

Este post contiene información **general** sobre la configuración de Google Analytics y el cumplimiento con la legislación vigente de España al día de la fecha. Los **requisitos legales podrían ser diferentes** atendiendo al tipo de empresa, localización y finalidad de la recogida de datos, por lo que es importante que se revise y consulte con una persona experta las necesidades legales de cada sitio web.