Nuxt.js
Integrate vTilt with Nuxt 3 / Nuxt 4 — npm package or inline script, identify on every authenticated page load, server-side events with Nitro.
vTilt drops into Nuxt 3/4 on the client. Nitro server routes can also emit events using the Node SDK so server actions and webhooks land on the same person record.
#1. Runtime config
Expose the token and ingest origin via nuxt.config.ts. The public block is readable on the client; values without public stay server-only.
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
vtiltTrackerToken: process.env.VTILT_TRACKER_TOKEN,
public: {
vtiltToken: process.env.NUXT_PUBLIC_VTILT_TOKEN,
vtiltHost: process.env.NUXT_PUBLIC_VTILT_HOST,
},
},
})# .env
NUXT_PUBLIC_VTILT_TOKEN=YOUR_PROJECT_TOKEN
NUXT_PUBLIC_VTILT_HOST=https://www.vtilt.com
VTILT_TRACKER_TOKEN=YOUR_PROJECT_TOKEN#2. Install & initialise
Choose how you load the Browser SDK. npm boots the SDK from a client-only plugin; the inline script injects a stub via useHead with no package to install. Both expose the same window.vt global — the rest of this guide is identical either way.
Install the package:
npm install @v-tilt/browserCreate plugins/vtilt.client.ts — the .client suffix keeps it out of SSR:
// plugins/vtilt.client.ts
import { vt } from '@v-tilt/browser'
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig()
vt.init(config.public.vtiltToken, {
api_host: config.public.vtiltHost,
autocapture: true,
capture_pageview: false, // captured on Vue Router navigation below
capture_pageleave: true,
})
const router = useRouter()
router.afterEach((to, from) => {
vt.capture('$pageview', {
$current_url: window.location.href,
$pathname: to.fullPath,
$referrer: from.fullPath,
})
})
return { provide: { vt } }
})Now useNuxtApp().$vt returns the SDK from any component.
#3. Identify on every authenticated page load
// plugins/vtilt-identify.client.ts
import { vt } from '@v-tilt/browser'
export default defineNuxtPlugin(() => {
const user = useState<{ id: string; email: string } | null>('user')
watchEffect(() => {
if (user.value) {
vt.identify(user.value.id, { email: user.value.email })
}
})
})See Identify & alias for the full model.
#4. Server-side events from Nitro
For events from server routes, install the Node SDK:
npm install @v-tilt/nodeReuse a single client across requests:
// server/utils/vtilt.ts
import { VTiltNode } from '@v-tilt/node'
let _client: VTiltNode | null = null
export function vtilt() {
if (!_client) {
const cfg = useRuntimeConfig()
_client = new VTiltNode(cfg.vtiltTrackerToken, {
host: cfg.public.vtiltHost,
})
}
return _client
}// server/api/checkout.post.ts
import { vtilt } from '~/server/utils/vtilt'
export default defineEventHandler(async event => {
const body = await readBody(event)
vtilt().capture({
distinctId: body.userId,
event: 'purchase_completed',
properties: { amount: body.amount },
})
await vtilt().shutdown()
return { ok: true }
})#Next steps
- Vue + PHP integration guide — the same identify-on-page-load pattern with a PHP back-end.
- Identify & alias — full identification model.
- Reverse proxy — block-resistant ingestion.
- Node SDK / Capture, identify & alias — server-side event shapes.