All integration guides

Integration guide

Analytics in Nuxt

A browser-only plugin creates the SDK, counts router navigations and exposes $analytics to components. Works with SSR, SSG and SPA mode.

Before you start

  • Nuxt 3 (or 4).
  • Your site_key, and your domain under Allowed origins.

Installation

  1. 1Install the SDK and set the key

    Nuxt fills runtimeConfig.public from NUXT_PUBLIC_* environment variables.

    npm install @racoelho/analytics
    nuxt.config.ts
    export default defineNuxtConfig({
      runtimeConfig: {
        public: {
          analisaSiteKey: '',
        },
      },
    })
    .env
    NUXT_PUBLIC_ANALISA_SITE_KEY=YOUR_SITE_KEY
  2. 2Create the plugin

    The .client suffix makes Nuxt load the plugin in the browser only — the SDK never runs on the server.

    plugins/analytics.client.ts
    import { Analytics } from '@racoelho/analytics'
    
    export default defineNuxtPlugin(() => {
      const config = useRuntimeConfig()
      // the .client suffix makes this run in the browser only
      const analytics = new Analytics({ siteKey: config.public.analisaSiteKey })
    
      useRouter().afterEach((to, from) => {
        // only when the path changes; the first load is already counted
        if (to.path !== from.path) analytics.pageview()
      })
    
      return { provide: { analytics } }
    })

Events and goals

In any component, get $analytics from useNuxtApp() and call track(name, properties).

components/NewsletterButton.vue
<script setup lang="ts">
const { $analytics } = useNuxtApp()

function subscribe() {
  $analytics.track('newsletter_signup', { place: 'footer' })
}
</script>

<template>
  <button @click="subscribe">Subscribe</button>
</template>

Create a newsletter_signup event goal in the dashboard. Since the plugin is client-only, use $analytics in event handlers or onMounted, never during server rendering.

Page navigation

After the first load Nuxt navigates without reloading, and the SDK does not notice that on its own — the plugin’s afterEach counts each new page. Query-string-only changes don’t count as a new page.

Check that it works

  1. Open the published site in a normal window, with no ad blocker.
  2. In your browser devtools, Network tab, filter by v1/i: you should see a POST with status 200 within 3 seconds (or when you leave the page).
  3. In the dashboard, events show up in about 30 seconds.
  4. Navigate with a <NuxtLink> and look for a new page_view in the next POST.

Troubleshooting

$analytics is undefined in a component
The code ran on the server, where the .client plugin doesn’t exist. Move the call into a click handler or onMounted.
The request returns 403 (origin_not_allowed)
Your domain isn’t in Allowed origins in the site settings. Add the exact origin — with https://, with and without www, plus test addresses like http://localhost:3000 if you want to measure in development.
No request shows up in the Network tab
The SDK honors Do Not Track by default: if your browser sends DNT, nothing is sent. Test in another browser or profile. Ad blockers can also block the script.
Pageviews show up twice
The SDK was initialized twice (for example, pasted in the theme and also added by a plugin). Keep a single instance per page.

Create your account and grab the site_key

Free up to 10K events a month, no credit card.

Create a free account
Nuxt analytics: a client plugin in 3 steps · Analisa