vTilt
Why vTiltHow It WorksFeaturesFAQDocs
Docs / TanStack Start
Quick startEvent forwarding
MCP server
Guides
OverviewAuthenticationOAuthAgent skills (prompts)AI intelligenceGoogle Ads
Client setup
CursorClaude DesktopVS CodeCodex
Realtime
Debug ViewRealtime Dashboard
Integration guides
Frontend frameworks
Next.jsNuxt.jsVue.jsReactReact RouterRemixGatsbySvelte / SvelteKitAstroAngularTanStack StartDocusaurus
Backend frameworks
NestJSHonoCloudflare WorkersDjangoFlaskLaravelPhoenixRuby on Rails
Backend languages
PythonPHPRubyElixirGoJava.NET / C#Rust
Stack guides
Vue + PHP
SDK
Browser SDK
InstallScript bundlesEvent trackingAutocaptureIdentify & aliasWeb VitalsSession recordingChat widgetFeature readinessRemote configurationReverse proxyDebug logging
Node SDK
Install & setupCapture, identify & aliasContext & shutdown

Documentation

vTilt
Quick startEvent forwarding

MCP server

Realtime

Debug ViewRealtime Dashboard

Integration guides

Next.jsNuxt.jsVue.jsReactReact RouterRemixGatsbySvelte / SvelteKitAstroAngularTanStack StartDocusaurus

SDK

DocsIntegration guidesTanStack Start

TanStack Start

Integrate vTilt with TanStack Start — npm package or inline script, navigations via TanStack Router, server functions with the Node SDK.

TanStack Start is a full-stack React framework built on TanStack Router. vTilt initialises on the browser side; TanStack server functions can call the Node SDK for server-side events.

#1. Add your environment variables

# .env
VITE_VTILT_TOKEN=YOUR_PROJECT_TOKEN
VITE_VTILT_HOST=https://www.vtilt.com
VTILT_TRACKER_TOKEN=YOUR_PROJECT_TOKEN
text

#2. Install & initialise

Choose how you load the Browser SDK. npm initialises the SDK in __root.tsx; the inline script drops a stub in your root document 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/browser
bash

Initialise in the root route component and emit pageviews on navigation:

// src/routes/__root.tsx
import { createRootRoute, Outlet, useRouterState } from '@tanstack/react-router'
import { useEffect } from 'react'
import { vt } from '@v-tilt/browser'

export const Route = createRootRoute({ component: RootComponent })

function RootComponent() {
  useEffect(() => {
    vt.init(import.meta.env.VITE_VTILT_TOKEN, {
      api_host: import.meta.env.VITE_VTILT_HOST,
      autocapture: true,
      capture_pageview: false,
      capture_pageleave: true,
    })
  }, [])

  const location = useRouterState({ select: s => s.location })
  useEffect(() => {
    vt.capture('$pageview', {
      $current_url: window.location.href,
      $pathname: location.pathname + location.search,
    })
  }, [location.pathname, location.search])

  return <Outlet />
}
tsx

Tip

Tip: Need chat on first paint? Swap array.js for array.chat.js and add chat: { enabled: true }. See Script bundles.

#3. Identify users

Use a route loader to fetch the current user, then identify on the client. Re-runs on every navigation, so logged-in visitors are identified on every page load.

// src/routes/__root.tsx (continued)
export const Route = createRootRoute({
  beforeLoad: async () => {
    const user = await fetchCurrentUser()
    return { user }
  },
  component: RootComponent,
})

function RootComponent() {
  const { user } = Route.useRouteContext()
  useEffect(() => {
    if (user) vt.identify(user.id, { email: user.email })
  }, [user])
  return <Outlet />
}
tsx

Important

Important: beforeLoad runs on both server and client; calling vt.identify only inside a useEffect keeps the SDK out of the SSR pass. See Identify & alias for the full model.

#4. Server functions

For server-side events, install the Node SDK:

npm install @v-tilt/node
bash
// src/lib/vtilt.server.ts
import { VTiltNode } from '@v-tilt/node'

export const vtilt = new VTiltNode(process.env.VTILT_TRACKER_TOKEN!, {
  host: process.env.VITE_VTILT_HOST,
})
typescript
// src/server-fns/checkout.ts
import { createServerFn } from '@tanstack/start'
import { vtilt } from '~/lib/vtilt.server'

export const completeCheckout = createServerFn({ method: 'POST' })
  .validator((data: { userId: string; amount: number }) => data)
  .handler(async ({ data }) => {
    vtilt.capture({
      distinctId: data.userId,
      event: 'purchase_completed',
      properties: { amount: data.amount },
    })
    await vtilt.shutdown()
    return { ok: true }
  })
typescript

#Next steps

  • Identify & alias — anonymous → known user merge.
  • Reverse proxy — block-resistant ingestion.
  • Node SDK — server-side event shapes.
PreviousAngularIntegration guidesNextDocusaurusIntegration guides

On this page

  • 1. Add your environment variables
  • 2. Install & initialise
  • 3. Identify users
  • 4. Server functions
  • Next steps