Framework adapters
Copy-paste adapter examples for Next.js, React Router, Remix, and Nuxt so Callra keeps SPA route metadata accurate.
Callra's shared script.js snippet works everywhere, but for SPAs with framework routing the adapter packages are the best install path.
They do three things for you:
- mount the shared tracker once
- keep
route_templatealigned with your framework's dynamic route pattern - send SPA pageviews without requiring manual
window.va('route', ...)calls
Use the raw snippet only when you cannot mount a framework adapter.
When to use an adapter
Use an adapter if your app has client-side routing and you care about readable route reports such as:
/docs/[slug]/dashboard/[siteId]/blog/[...segments]
Without route metadata, Callra can still track page URLs, but route-based Web Analytics and Speed Insights breakdowns may collapse into exact paths or (unknown route).
Shared requirements
Install the package for your framework and pass:
siteId: the Callra site idhost: your Callra app URL, such ashttps://analytics.example.com
All examples below assume this site id:
const siteId = 'site_123';
const host = 'https://analytics.example.com';Next.js
For the App Router, mount the adapter once in a client component near the root.
'use client';
import { Analytics } from '@callra/analytics-next';
export function CallraAnalytics() {
return <Analytics siteId="site_123" host="https://analytics.example.com" />;
}Then render that component from app/layout.tsx or from a shared providers wrapper.
import { CallraAnalytics } from './callra-analytics';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
{children}
<CallraAnalytics />
</body>
</html>
);
}React Router
Mount the adapter once inside your app shell.
import { Analytics } from '@callra/analytics-react-router';
export function App() {
return (
<>
<Analytics siteId="site_123" host="https://analytics.example.com" />
{/* your router UI */}
</>
);
}Remix
Mount the adapter once in the main app document.
import { Analytics } from '@callra/analytics-remix';
import { Outlet } from '@remix-run/react';
export default function App() {
return (
<html>
<body>
<Analytics siteId="site_123" host="https://analytics.example.com" />
<Outlet />
</body>
</html>
);
}Nuxt
Register the adapter in a plugin so it initializes once.
import { defineNuxtPlugin } from '#app';
import { injectNuxtAnalytics } from '@callra/analytics-nuxt';
export default defineNuxtPlugin(() => {
injectNuxtAnalytics({
siteId: 'site_123',
host: 'https://analytics.example.com'
});
});Optional runtime settings
All adapters ultimately drive the same Callra runtime, so you can still pass normal runtime options such as environment labels.
<Analytics
siteId="site_123"
host="https://analytics.example.com"
environment="staging"
/>You can also keep using custom events:
window.va('event', 'Signup', {
plan: 'pro',
location: 'pricing-page'
});If you cannot use an adapter
Stay on the raw snippet and send route metadata yourself whenever the framework route changes.
window.va('route', { route: '/docs/[slug]' });That fallback works, but adapters are safer because they keep route state and pageview timing aligned automatically.