# TanStack Start - Docs This tutorial shows how to integrate PostHog with a [TanStack Start](https://tanstack.com/start) app for both client-side and server-side analytics. ## Installation Install the required packages: Terminal PostHog AI ```bash npm install @posthog/react posthog-node ``` - `@posthog/react` - React package for our [JS Web SDK](/docs/libraries/js.md) for client-side usage - `posthog-node` - PostHog [Node.js SDK](/docs/libraries/node.md) for server-side event capture ## Initialize PostHog on the client Wrap your app with `PostHogProvider` in your root route with your project token, host, and other options. src/routes/\_\_root.tsx PostHog AI ```jsx // src/routes/__root.tsx import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router' import { PostHogProvider } from '@posthog/react' export const Route = createRootRoute({ head: () => ({ meta: [ { charSet: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, ], }), shellComponent: RootDocument, }) function RootDocument({ children }: { children: React.ReactNode }) { return ( {children} ) } ``` Once the provider is in place, PostHog automatically captures pageviews, sessions, and web vitals. ## Capture events on the client Use the `usePostHog` hook from `@posthog/react` in any component to capture custom events: src/routes/checkout.tsx PostHog AI ```jsx import { usePostHog } from '@posthog/react' function CheckoutButton({ orderId, total }: { orderId: string; total: number }) { const posthog = usePostHog() const handleClick = () => { posthog.capture('checkout_started', { order_id: orderId, total: total, }) } return } ``` ### Identify users Call `posthog.identify()` when a user logs in to link their events to a user ID: TSX PostHog AI ```jsx import { usePostHog } from '@posthog/react' function LoginForm() { const posthog = usePostHog() const handleLogin = async (userId: string, email: string) => { // ... your login logic posthog.identify(userId, { email: email, }) posthog.capture('user_logged_in') } } ``` Call `posthog.reset()` on logout to clear the identified user. ## Initialize PostHog on the server Create a server-side PostHog client using `posthog-node`. Use a singleton pattern so you reuse the same client across requests: src/utils/posthog-server.ts PostHog AI ```typescript // src/utils/posthog-server.ts import { PostHog } from 'posthog-node' let posthogClient: PostHog | null = null export function getPostHogClient() { if (!posthogClient) { posthogClient = new PostHog( '', { host: 'https://us.i.posthog.com', flushAt: 1, flushInterval: 0, }, ) } return posthogClient } ``` ## Capture events on the server Use the server client in TanStack Start API routes to capture events server-side. Server-side capture is useful for tracking events that shouldn't be spoofable from the client, like purchases or authentication: src/routes/api/checkout.ts PostHog AI ```typescript // src/routes/api/checkout.ts import { createFileRoute } from '@tanstack/react-router' import { json } from '@tanstack/react-start' import { getPostHogClient } from '../../utils/posthog-server' export const Route = createFileRoute('/api/checkout')({ server: { handlers: { POST: async ({ request }) => { const body = await request.json() const posthog = getPostHogClient() posthog.capture({ distinctId: body.userId, event: 'item_purchased', properties: { item_id: body.itemId, price: body.price, source: 'api', }, }) return json({ success: true }) }, }, }, }) ``` The server-side `capture` call requires a `distinctId` (the user identifier), an `event` name, and optional `properties`. ## Next steps Installing the JS Web SDK and Node SDK means all of their functionality is available in your TanStack Start project. To learn more about this, have a look at our [JS Web SDK docs](/docs/libraries/js/usage.md) and [Node SDK docs](/docs/libraries/node.md). ### Community questions Ask a question ### Was this page useful? HelpfulCould be better