Analytics for Vite React Project: Litlyx Setup Guide

Set up GDPR-compliant analytics for your Vite React project with Litlyx. Cookieless tracking for single-page apps, no banners required.

Close-up macro shot of React component code showing useEffect and useLocation hooks with Litlyx initialization functions (Lit.init and Lit.e

Analytics for Your Vite React Project: A Step-by-Step Setup with Litlyx

Why Does a Vite React Project Need a Different Analytics Approach?

A Vite React project is a single-page application. That one fact changes everything about how analytics must work. Traditional script-tag analytics fire on full page loads, but SPAs never reload the page after the initial render, so those tools miss the vast majority of user navigation. You need an approach built specifically for client-side rendering environments.

When a user clicks a link inside a React app, the browser intercepts that navigation through the History API or React Router, swaps out components, and updates the URL without ever making a new HTTP request to your server. A standard analytics snippet sitting in index.html has no idea any of this happened. The gap this creates is not subtle: as React applications rely on client-side rendering, which means traditional analytics scripts that only fire on full page loads will miss most of your traffic, you are not losing a small rounding error of data; you are losing almost all of it.

The second challenge is legal. GDPR and the ePrivacy Directive require informed user agreement before placing identifying files on a device. Session-identifying analytics solutions need agreement banners, and those banners create real friction. Users dismiss them, abandon pages, or opt out entirely, which distorts your data and inflates your measured bounce rate before a single real interaction occurs.

Cookieless tracking solves both problems at once. Privacy-first analytics that collect no personal data fall outside the scope of ePrivacy requirements, so the banner disappears entirely. Your numbers become cleaner, your user experience improves, and your legal exposure drops. Built from the ground up for exactly this scenario, Litlyx is fully GDPR compliant and EU hosted with no cookies and no personal data collection: accurate SPA page-view tracking, no agreement banner required, and user-friendly insights your whole team can act on.

What Tools and Prerequisites Do You Need Before Starting?

Honestly, the list is shorter than you might expect. Before adding analytics for your Vite React project, you need four things in place: a supported Node.js version, a Vite React app, a Litlyx account, and React Router. Getting these ready takes less than ten minutes, and the rest of the setup follows a clear, linear path.

Node.js and a package manager. You need Node.js 18 or later installed on your machine, along with npm, pnpm, or yarn. Any of the three package managers works fine throughout this tutorial. If you are unsure which version you have, run node -v in your terminal to check.

A Vite React project. If you already have one, great. TypeScript and JavaScript projects both work without any extra configuration. If you are starting from scratch, the next section walks through scaffolding a fresh app. Vite's build tool supports native ES modules and Hot Module Replacement, which makes the development loop fast and predictable.

A free Litlyx account and project ID. Sign up at litlyx.com and create a new project. The dashboard generates a unique project ID that you will use to initialize the SDK. Litlyx can be installed via npm with `npm install litlyx-js` and set up in just a few lines of code, so your first data point is never far away.

React Router v6. The example in this tutorial uses React Router v6 for client-side navigation. The page-view tracking pattern we cover applies equally well to other routers, so treat it as a transferable approach rather than a hard dependency.

How Do You Scaffold a Fresh Vite React App?

Getting a Vite React project off the ground takes only a few commands. Once the base app is running, we add React Router so our analytics can respond to client-side navigation later.

Scaffolding the project

Run the following command to generate a TypeScript React project using Vite's native ES module dev server:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

The dev server starts on localhost:5173 by default. Confirm you see the Vite welcome page before moving on. The file tree at this point looks like this:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

The files we will touch in later sections are main.tsx, App.tsx, and a new hooks/ folder.

Adding React Router

React Router v6 installs with a single command and pairs naturally with Vite's client-side rendering model:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Open main.tsx and wrap the <App /> component in a BrowserRouter:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

This gives every child component access to the location context we need for page-view tracking, which we set up in the next section.

How Do You Install and Configure Litlyx in a Vite React Project?

Installing Litlyx takes only a few minutes. No complex configuration required. The SDK is cookieless and collects no personal information, so you skip the banner logic entirely and get straight to capturing real data.

Installing the Package

Open your terminal at the project root and run:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

That single command pulls in the litlyx-js SDK, which you initialize with Lit.init('your_workspace_id'). The package is intentionally lightweight, so it adds negligible overhead to your Vite bundle.

Initializing with Your Project ID

The right place to initialize Litlyx is your app entry point, typically main.tsx. You want the SDK to load once, before any React component mounts, so every subsequent page view and custom event is captured from the start.

Here is what main.tsx looks like after the change:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Notice that Lit.init() is called before ReactDOM.createRoot(). This ordering guarantees the SDK is ready before any component fires events.

Using Environment Variables

Hardcoding your project ID directly in source files is a common mistake. Anyone with access to your repository would have access to your analytics workspace. Vite makes this easy to avoid with its built-in environment variable system.

Create a .env.local file at the project root:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Vite automatically exposes any variable prefixed with VITE_ to your client-side code via import.meta.env. Add .env.local to your .gitignore so it never reaches source control. When you deploy to production, set VITE_LITLYX_ID as an environment variable in your hosting platform instead.

Litlyx is fully GDPR-compliant and EU-hosted with no cookies and no personal data collection, so there is no consent management platform to wire up and no conditional initialization logic to write. The SDK is always safe to call on page load, for every visitor, without any privacy risk. That alone removes a significant layer of complexity that session-identifying solutions require.

How Do You Track Page Views Across SPA Routes?

Tracking page views in a Vite React app requires a route-change listener, not a simple script tag. React controls navigation entirely in the browser, swapping components without ever reloading the document, which is exactly why traditional analytics scripts that only fire on full page loads will miss most of your traffic. We need to hook into that routing layer directly.

The usePageTracking Hook

The cleanest solution is a small custom hook that watches the current location and fires a Litlyx event every time it changes. useLocation() from React Router returns a new object on every navigation, so a useEffect that depends on it runs exactly when we want: once per route change, reliably, with no duplicates.

Create a new file at src/hooks/usePageTracking.ts:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

That is the complete hook. It reads the current pathname from useLocation(), passes it as metadata, and fires Lit.event('pageview', ...) on every navigation. Litlyx collects no personal information and requires no agreement banner, so you can freely include the full pathname without any concern about capturing sensitive user data.

This pattern is more reliable than dropping a script tag into index.html for one clear reason. A static script fires once when the browser parses the document. After that, React owns navigation and the script never runs again. The useEffect hook, by contrast, runs on every render triggered by a location change, giving you an accurate count of every virtual page view your users generate.

Mounting the Hook in App.tsx

The hook must be called inside a component that sits under <BrowserRouter> in the tree, because useLocation() depends on the Router context. The right place is a small layout component or directly inside App.tsx, wrapped by the router.

Here is how App.tsx looks after adding the hook:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Notice that usePageTracking is called inside AppContent, not inside App itself. This separation is intentional. App renders the BrowserRouter, and any hook that calls useLocation() must be a child of that provider. Calling it at the wrong level throws a runtime error, so keeping AppContent as the bridge component avoids that pitfall entirely.

With this in place, every route transition your users make, whether they click a nav link, press the browser back button, or get redirected programmatically, will generate a Cookieless tracking event in your Litlyx dashboard with the correct pathname attached.

How Do You Send Custom Events for User Actions?

Custom events are where analytics for a Vite React project starts delivering real business value. A single call to Lit.event('event_name', { metadata }) placed anywhere inside a React component records that action in your Litlyx dashboard instantly, giving your team the data-driven decisions foundation they need.

Basic custom event

Recording a custom event requires almost no code. After Litlyx is installed and initialized with `Lit.init()`, every component in your app has access to the Lit object. You just import it and call Lit.event() on the interaction you care about.

Here is a signup button before adding analytics:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

And here is the same component after adding the event call:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

That is the entire change. One import, one function call.

Passing metadata

The optional metadata object is what separates basic event counting from genuinely precise analysis. When you call Lit.event('signup_click', { plan: 'free' }), the Litlyx dashboard groups events by those metadata values, so you can see exactly which plan tier or page variant is driving conversions.

Consider a pricing page with multiple plan options:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Now your dashboard shows signup_click broken down by plan: 'free', plan: 'pro', and so on. That granularity makes data-driven decisions far more actionable than a raw click count ever could.

One practical point worth calling out: because Litlyx is fully GDPR-compliant and collects no personal data, the metadata you pass should never include names, emails, or any personally identifiable information. Stick to behavioral attributes like plan names, button labels, or feature flags, and you stay well within privacy boundaries.

Events are processed through Litlyx's own infrastructure rather than executing purely as a browser-side script, which means they reach the dashboard even when users have browser-level script filters active. Your event counts stay accurate without any extra configuration on your side. Privacy-first analytics and reliable data collection are not a trade-off here; you get both.

How Do You Verify That Events Are Arriving in the Litlyx Dashboard?

Verification is straightforward. Open the real-time dashboard and start navigating around your local dev app. Events should appear within seconds, giving you immediate confirmation that the integration is working correctly.

Once you have the dashboard open, click through a few routes in your Vite React app. Each navigation triggers the usePageTracking hook, which fires a page view event. Watch the dashboard update live. That near-instant feedback is one of the clearest signals that your setup is correct, and it reflects exactly why Litlyx is fully GDPR-compliant and EU-hosted with no cookies and no personal data collection: there is no agreement flow slowing things down, so events flow straight through.

What metrics appear right away

The dashboard surfaces four key data points from the moment events start arriving:

  • Page views: total count of route changes recorded
  • Unique sessions: distinct visitor sessions within your chosen time window
  • Top pages: ranked list of the most visited routes in your app
  • Custom events: a separate panel showing every named event you have sent via Lit.event()

To isolate the signup_click event you added earlier, use the event name filter in the custom events panel. Type signup_click and the dashboard narrows the view to just those records, including any metadata like the plan field you passed. This makes data-driven decisions much more precise because you can see not just that the button was clicked, but which plan option users were selecting.

Moving from local to production

The same setup works in production without any code changes. You only need to swap the VITE_LITLYX_ID environment variable in your deployment environment to point at your production project ID instead of the development one. Set the variable in your hosting platform's environment configuration, trigger a new build, and your production traffic will appear in a separate dashboard project, keeping dev noise out of your real metrics.

What Does the Final Project Structure Look Like?

Four small changes. That is all it takes to add production-ready analytics to a Vite React project. The total lines of analytics code sits comfortably under 20, and the files that changed are exactly what you would expect: main.tsx, App.tsx, hooks/usePageTracking.ts, and .env.local.

Here is the condensed file tree showing only the modified pieces:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

To recap the four steps we took:

  1. Install the litlyx-js package via npm.
  2. Initialize Litlyx in main.tsx using the VITE_LITLYX_ID environment variable.
  3. Track page views with the usePageTracking hook that fires on every route change.
  4. Send custom events from components using Lit.event().

What we did not add is just as significant. Because Litlyx is fully GDPR-compliant and collects no personal data, there is no agreement banner logic anywhere in the codebase. There is no third-party script tag in index.html, and no personal information ever leaves the browser to an external vendor. This matters because, as the evidence confirms, traditional analytics scripts miss most traffic in SPAs anyway, so a script-tag approach would have been both legally risky and technically incomplete. Privacy-first analytics, done right, is simply the leaner path.

How Can You Extend This Setup for a Production Vite React App?

Look, the setup we have built so far works well in development, but a few small additions will make it genuinely production-ready. Separating dev and production credentials, abstracting the SDK behind a service module, and sharing results with your team are the natural next steps.

Environment-Specific Project IDs

Vite ships with built-in env modes out of the box. Create a .env.production file alongside your .env.local and define a separate VITE_LITLYX_ID value pointing to your production Litlyx project. When you run vite build, Vite automatically picks up the production file, so dev traffic never pollutes your live data. This is especially useful when you want clean funnel metrics from real users rather than your own test sessions.

An Analytics Service Module

As your app grows, scattering Lit.event() calls across dozens of components gets messy. A thin src/services/analytics.ts wrapper solves that. Export named functions like trackSignup(plan: string) that call the SDK internally. Components stay decoupled from litlyx-js, and if you ever swap analytics providers, you change one file rather than fifty.

Sharing Insights With Your Team

Litlyx is fully GDPR-compliant and EU-hosted, which means you can share the real-time dashboard with stakeholders without worrying about data residency questions. Non-technical teammates get user-friendly insights: top pages, session counts, custom event totals, all in one view. No SQL required.

Scaling to Other React Frameworks

Because Litlyx is cookieless and collects no personal information, the same initialization pattern transfers to Next.js or Remix with only minor adjustments around where Lit.init() runs. Privacy-first analytics does not care which React framework wraps it. The Litlyx documentation covers advanced features like funnels, retention curves, and custom dashboards if you want to push further from here.

Frequently asked questions

Does Litlyx work with React Router v6 and v7?

Yes, Litlyx works seamlessly with both React Router v6 and v7. The SDK integrates with React Router's location context to track page views when routes change client-side. Since Litlyx is router-agnostic, it captures navigation events regardless of which routing library you use. The setup involves listening to location changes and calling `Lit.event()` to log page views as users navigate within your SPA.

Do I need a consent banner when using Litlyx in a Vite React project?

No. Litlyx is cookieless and collects no personal data, so it falls outside GDPR and ePrivacy requirements. You don't need a consent banner, which improves user experience and keeps your analytics data clean. This is a key advantage over traditional analytics tools like Google Analytics GA4, which require consent banners in EU jurisdictions before tracking can begin.

Can I use Litlyx analytics with Vite's SSR mode?

Litlyx is designed for client-side tracking and works best in client-side rendering (CSR) environments. For Vite SSR projects, the SDK initializes on the client side after hydration. Server-side event tracking is not supported. If you need server-side analytics in an SSR setup, consider a hybrid approach where Litlyx handles client-side navigation and custom events.

How is Litlyx different from Google Analytics GA4 for a React SPA?

Litlyx is purpose-built for SPAs and requires no consent banner since it's cookieless and collects no personal data. GA4 uses cookies and requires GDPR consent in EU regions. Litlyx integrates directly with React Router to track client-side navigation automatically, while GA4 requires manual pageview tracking. Litlyx is EU-hosted and fully GDPR-compliant by design, making it simpler for privacy-conscious teams.

Will analytics events fire correctly after a Vite production build?

Yes. Litlyx events fire correctly after a Vite production build. The SDK is tree-shakeable and lightweight, so it bundles efficiently with your production code. Ensure your project ID is set via environment variables (e.g., `VITE_LITLYX_ID`) and properly referenced in your initialization code. Test event firing in your production build before deploying to catch any configuration issues early.

How do I track 404 pages in a Vite React app with Litlyx?

Create a 404 NotFound component in React Router and wrap it with a useEffect hook that fires a Litlyx event when the component mounts. Use `Lit.event('404_page_view')` or similar to log the event. Alternatively, listen to location changes in a custom hook and check if the route matches any defined routes; if not, fire a 404 event. This captures all unmatched navigation attempts.

Is the Litlyx SDK compatible with React 18 and React 19?

Yes, Litlyx is compatible with React 18 and React 19. The SDK is framework-agnostic and works independently of React's version. It integrates via hooks and event listeners, not React internals, so version upgrades don't affect Litlyx functionality. Test your setup after upgrading React to ensure your custom event tracking logic still works as expected.

How many custom events can I send on the free Litlyx plan?

Litlyx's free plan includes unlimited custom events. You can track as many user interactions—button clicks, form submissions, video plays, or custom conversions—as needed without hitting a limit. Pricing tiers scale based on page views and data retention, not event volume, making Litlyx cost-effective for analytics-heavy React applications.