vTilt
Why vTiltHow It WorksFeaturesFAQDocs
Docs / Astro
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 guidesAstro

Astro

Integrate vTilt with Astro — npm package or inline script in your base layout, framework-island compatibility, server-side events.

Astro is islands-first: most of the page is static HTML and you opt into JS only where you need interactivity. vTilt fits in via a top-level <script> in your base layout, so every page boots the SDK without an island wrapper.

#1. Add your environment variables

# .env
PUBLIC_VTILT_TOKEN=YOUR_PROJECT_TOKEN
PUBLIC_VTILT_HOST=https://www.vtilt.com
text

#2. Install & initialise

Choose how you load the Browser SDK. npm uses a bundled <script> in your layout; the inline script uses an is:inline stub 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

Astro <script> tags are bundled and treeshaken by Vite. Add one in your shared layout so every page initialises the SDK and identifies the user:

---
// src/layouts/Base.astro
const { user = null } = Astro.props
---
<!doctype html>
<html lang="en">
  <head>
    <slot name="head" />
    <script type="module" define:vars={{ user }}>
      import { vt } from '@v-tilt/browser'

      vt.init(import.meta.env.PUBLIC_VTILT_TOKEN, {
        api_host: import.meta.env.PUBLIC_VTILT_HOST,
        autocapture: true,
        capture_pageview: true,
        capture_pageleave: true,
      })

      if (user) vt.identify(user.id, { email: user.email })
    </script>
  </head>
  <body>
    <slot />
  </body>
</html>
astro

Important

Important: Identifying users in the layout means every authenticated page load identifies — not just the login event. See Identify & alias for the full model.

Tip

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

#3. Capture events from islands

With the npm package, import vt in islands. With the inline script, use window.vt.

// src/components/CtaButton.tsx
import { vt } from '@v-tilt/browser'

export default function CtaButton() {
  return (
    <button onClick={() => vt.capture('cta_clicked', { location: 'hero' })}>
      Get started
    </button>
  )
}
tsx
---
import CtaButton from '../components/CtaButton'
---
<CtaButton client:load />
astro

#4. Astro view transitions

If you use Astro view transitions, the page doesn't fully reload on navigation. Re-emit $pageview from the astro:after-swap event:

<script>
  import { vt } from '@v-tilt/browser'
  document.addEventListener('astro:after-swap', () => {
    vt.capture('$pageview', { $current_url: window.location.href })
  })
</script>
html

#5. Server-side events from API routes (SSR mode)

For events from SSR pages and API routes, install the Node SDK:

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

export const vtilt = new VTiltNode(import.meta.env.VTILT_TRACKER_TOKEN, {
  host: import.meta.env.PUBLIC_VTILT_HOST,
})
typescript
// src/pages/api/checkout.ts
import type { APIRoute } from 'astro'
import { vtilt } from '../../lib/vtilt'

export const POST: APIRoute = async ({ request }) => {
  const { userId, amount } = await request.json()
  vtilt.capture({
    distinctId: userId,
    event: 'purchase_completed',
    properties: { amount },
  })
  await vtilt.shutdown()
  return new Response(JSON.stringify({ ok: true }))
}
typescript

#Next steps

  • Identify & alias — anonymous → known user merge.
  • Autocapture — what's captured automatically.
  • Node SDK — server-side event shapes.
PreviousSvelte / SvelteKitIntegration guidesNextAngularIntegration guides

On this page

  • 1. Add your environment variables
  • 2. Install & initialise
  • 3. Capture events from islands
  • 4. Astro view transitions
  • 5. Server-side events from API routes (SSR mode)
  • Next steps