How to Integrate Google Analytics with Nuxt 3 (with Cookie Consent)

Every time I need to set up Google Analytics for a Nuxt project, I forget how to do it. To help myself and others, I decided to do a quick write up of the solution that will hopefully help some people (including myself) for future projects.

This implementation includes a cookie consent banner that allows users to opt-in or opt-out of tracking. This is important to comply with GDPR and other privacy regulations.


Create Google Analytics Account

Before starting, make sure that you have a Google Analytics account set up. If you don't have one yet, you can create an account here. The process is straightforward - simply enter info about your website and follow the instructions.

When asked to create a data-stream, select Web as the platform and enter your website URL. You will receive a tracking ID that you will need to add to your Nuxt project.

Set up Google Tag Manager

First, we need to set up Google Tag Manager. If you haven't done this yet, keep reading. If you already have Google Tag Manager set up, you can skip this step.

Create Account and Container

Visit the Google Tag Manager website and create an account. You will need a Google account to do this.

To create your account, click on the "Create Account" button and follow the instructions. Enter your app details and select Web as the target platform.

After creating your account, you will be redirected to your dashboard. In the topbar of the dashboard, you will find your Container ID. It should look something like GTM-XXXXXXX. Remember where to find this Container ID as you will need it later.

Create Tag

On the Google Tag Manager dashboard, click on the "New Tag" button to create a new tag.

In the "Tag Configuration" section, select Google Analytics -> Google Tag as the tag type. You will need to enter a Tag-ID.

You can find this ID in your Google Analytics account by navigating to Admin -> Property Settings -> Data collection and modification -> Data Streams. Click on the corresponding data stream, and copy the Measurement ID, then add it into the Tag-ID field in Google Tag Manager.

In the "Triggering" section, select Initialization - All Pages to make sure that the tag is triggered on every page.


Install Dependencies

First, we need to install the @gtm-support/vue-gtm package. This package is a wrapper around Google Tag Manager and makes it easy to integrate with Vue.

npm i @gtm-support/vue-gtm

Next, we need to install js-cookie to manage cookies in our Nuxt project.

npm i js-cookie

Configure Google Tag Manager for Nuxt

To configure Google Tag Manager for Nuxt, we need to create a plugin that initializes the Google Tag Manager script.

Create a new file in the plugins directory of your Nuxt project. Name it vue-gtm.client.js.

import { createGtm } from '@gtm-support/vue-gtm'
import Cookies from 'js-cookie'

export default defineNuxtPlugin((nuxtApp) => {
  const runtimeConfig = useRuntimeConfig().public
  const consentGiven = Cookies.get('userConsent') === 'granted'
  const router = useRouter()

  nuxtApp.vueApp.use(
    createGtm({
      id: runtimeConfig.gtm_id,
      defer: false,
      compatibility: false,
      enabled: runtimeConfig.gtm_enabled && consentGiven,
      debug: runtimeConfig.gtm_debug,
      loadScript: true,
      vueRouter: router,
      trackOnNextTick: false,
    }),
  )
})

Note that we reference the gtm_id, gtm_enabled, and gtm_debug properties from the runtime config. To set these properties, we need to add them to the nuxt.config.js file.

export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      gtm_id: process.env.GTM_ID,
      gtm_enabled: true,
      gtm_debug: process.env.ENVIRONMENT === 'development' ? true : false,
    },
  },
})

In the nuxt.config.js file, we set the gtm_id to the Google Tag Manager Container ID (GTM-XXXXXXX) and the gtm_debug property to true if the environment is set to development.

In our plugin, we check if the user has given consent by checking the userConsent cookie. If the cookie is set to granted, we enable Google Tag Manager. If the cookie is not set or set to denied, Google Tag Manager is disabled.

To set the userConsent cookie, we need to create a cookie consent banner.

Create Cookie Consent Banner

To create a cookie consent banner, we need to create a new component. Create a new file in the components directory of your Nuxt project. Name it CookieConsent.vue.

I'm using Tailwind CSS for styling, but you can use any CSS framework or custom styles.

<template>
  <div
    v-if="showBanner"
    class="max-w-screen fixed bottom-0 w-full bg-black p-6"
  >
    <div
      class="flex flex-col justify-between gap-6 text-white lg:mx-auto lg:max-w-7xl lg:flex-row lg:items-center"
    >
      <div>
        <p class="font-display font-semibold">Cookies</p>
        <p class="text-sm">
          We use cookies to improve your experience. Do you accept?
        </p>
      </div>
      <div class="flex gap-4">
        <button
          class="flex-grow rounded bg-gray-800 px-3 py-2 text-gray-200 lg:flex-grow-0"
          @click="declineCookies"
        >
          Decline
        </button>
        <button
          class="flex-grow rounded bg-blue-600 px-3 py-2 font-semibold text-white lg:flex-grow-0"
          @click="acceptCookies"
        >
          Accept
        </button>
      </div>
    </div>
  </div>
</template>

<script setup>
  import { ref, onMounted } from 'vue'
  import Cookies from 'js-cookie'
  import { useGtm } from '@gtm-support/vue-gtm'

  const gtm = useGtm()

  const showBanner = ref(false)

  const acceptCookies = () => {
    Cookies.set('userConsent', 'granted', { expires: 365 })
    gtm.enable(true)
    showBanner.value = false
  }

  const declineCookies = () => {
    Cookies.set('userConsent', 'denied', { expires: 365 })
    gtm.enable(false)
    showBanner.value = false
  }

  onMounted(() => {
    const consentStatus = Cookies.get('userConsent')
    if (consentStatus === 'granted') {
      gtm.enable(true)
      showBanner.value = false
    } else if (consentStatus === 'denied') {
      showBanner.value = false
      gtm.enable(false)
    } else {
      showBanner.value = true
    }
  })
</script>

In the CookieConsent.vue component, we check if the userConsent cookie is set. If the cookie is set to granted, we enable Google Tag Manager and hide the banner. If the cookie is set to denied, we hide the banner and disable Google Tag Manager. If the cookie is not set, we show the banner.

To make the CookieConsent component available on every page, we need to add it to the layout component. If you don't have a layout component yet, you can create one in the layouts directory of your Nuxt project.

<!-- layouts/default.vue -->
<template>
  <!-- Other components (header, etc.) -->
  <slot />
  <CookieBanner />
</template>

Now, the CookieConsent banner will be displayed on every page of your Nuxt project. Users can opt-in or opt-out of tracking by clicking the "Accept" or "Decline" button.

To test the implementation, run your Nuxt projects and open the developer tools. Select the "Elements" tab and confirm that the Google Tag Manager script is loaded when the user accepts cookies. You can also check the cookies in the "Application" tab to see if the userConsent cookie is set.


Next Steps

That's it, you have successfully integrated Google Analytics with Nuxt 3 and added a cookie consent banner to comply with privacy regulations.

I hope this tutorial was useful for you. If you have any questions, feel free to reach out to me at pk@pkundr.com.

I also offer services in the areas of Product Management and Web development. If you need help with a project, I would be happy to discuss it with you.

Philipp