---
title: "How to add product analytics to your app with v0"
description: "Connect v0 to Amplitude's MCP servers, add your API key as a NEXT_PUBLIC_ variable, have v0 install the SDK, review the diff, and save the rules."
canonical: "https://amplitude.com/en-us/build/v0-product-analytics"
---

# How to add product analytics to your app with v0

Connect v0 to Amplitude's MCP servers, add your API key as a NEXT_PUBLIC_ variable, have v0 install the SDK, review the diff, and save the rules.

Source: https://amplitude.com/en-us/build/v0-product-analytics

---

# How to add product analytics to your app with v0

Connect v0 to Amplitude's MCP servers, add your API key as an environment variable the browser build can read, and hand v0 one prompt that installs the SDK the docs recommend. Then review its diff, add one event that matches your taxonomy, and save the rules as a v0 Instruction. About 15 minutes, all copy-paste.

- v0
- Next.js
- App Router
- Amplitude MCP
- 15 min

Chris Tam · Last updated 6 October 2026

v0 builds full-stack Next.js apps from chat prompts. It can add [product analytics](https://amplitude.com/amplitude-analytics) to the app it builds in a single chat, as long as it reads current Amplitude docs and your API key reaches the browser bundle.

In this tutorial, you'll connect v0 to Amplitude, add your API key as an environment variable, have v0 install the SDK, review its changes, and save the rules as a v0 Instruction.

## What you'll build

A v0 chat connected to the Amplitude MCP server and the Docs MCP server, a Next.js app instrumented with `@amplitude/unified` and initialized only in the browser, signed-in users identified by their auth user ID, one `Report Exported` event named to match your existing taxonomy, and a v0 Instruction that keeps v0 on those conventions. By the end you'll see live events in your Amplitude project.

## Prerequisites

- A v0 account and a chat with an app you can edit. v0 builds with Next.js, React, and TypeScript; this page assumes the App Router, with an `app/` directory and `app/layout.tsx`.
- An Amplitude account with access to a project, and that project's API key. In Amplitude, go to Settings > Projects > your project > General.

No Amplitude account yet? A free account is enough for this tutorial; nothing here needs a paid Amplitude plan. [Sign up for free](https://app.amplitude.com/signup) to get your project API key.

## 1. Connect v0 to Amplitude

You add both servers to v0 as custom MCP servers. Amplitude's MCP server works with any client that supports remote HTTP servers with OAuth, and v0 does; the [setup guide for MCP clients](https://amplitude.com/docs/amplitude-ai/amplitude-mcp/other-clients) has the full reference.

The first is the authenticated Amplitude MCP server, which reads your projects and tracking plan with your own Amplitude permissions:

1. In the v0 prompt form, open the **+** menu and select **MCPs**.
2. Choose to configure a custom MCP server instead of a preset.
3. Name it `Amplitude` and set the server URL to `https://mcp.amplitude.com/mcp`. If your Amplitude data lives in the EU region, use `https://mcp.eu.amplitude.com/mcp` instead.
4. Choose **OAuth** as the authentication type, save, and complete the Amplitude sign-in when prompted.

The second is the public [Docs MCP server](https://amplitude.com/docs/amplitude-ai/docs-mcp-server), which serves current Amplitude documentation:

1. From the same **MCPs** menu, configure another custom MCP server.
2. Name it `Amplitude Docs` and set the server URL to `https://amplitude.com/docs/api/mcp`.
3. Choose **No Auth**, since the Docs server is public, and save.

Make sure both servers are enabled, then check them:

Prompt for v0

```text
What Amplitude projects can I access? Then use the Amplitude Docs MCP
server to search the docs for "Browser Unified SDK" and tell me which
page you found.
```

A list of your projects plus a docs page title means both servers work. If your permission mode is **Ask Permissions**, v0 asks you to confirm tool calls that no permission rule allows; approve them.

**Why.** In v0, MCP servers give tools to the agent while it generates code. The app v0 builds can't call them, and the Amplitude MCP server isn't an ingestion endpoint anyway. It's how v0 reads your taxonomy and checks results; the SDK still does the sending. The Docs server is what stops v0 from installing a package it remembers instead of the one the Quickstart recommends today.

## 2. Add your API key as an environment variable

This is the step v0 makes easy to get wrong. v0 apps are Next.js, and Next.js only exposes a variable to the browser if its name starts with `NEXT_PUBLIC_`. v0 also keeps separate values for Development, Preview, and Production, and its in-chat preview reads only the Development ones.

Open **Project menu** (`...`) > **Settings** > **Environment Variables** and add:

Project menu > Settings > Environment Variables

```sh
NEXT_PUBLIC_AMPLITUDE_API_KEY=your-project-api-key
```

Apply it to all three environments: Development, Preview, and Production. Don't mark it as sensitive; v0's preview can't read sensitive variables. Add the key here rather than pasting it into the chat, so it never ends up hardcoded in a source file.

**Why.** Next.js inlines `NEXT_PUBLIC_` values into the JavaScript bundle at build time. A key that exists only in Development works in the chat preview and comes through as undefined in your published app. A key you add or change after publishing reaches the published app only after you publish again. Shipping this key to the browser is fine: the Amplitude project API key is public, and its scope is limited to the minimum needed to ingest data, so it isn't a secret the way a server credential is.

## 3. Run the install prompt

Paste this prompt into the chat. If you want v0 to plan before it edits files, check the built-in **Plan Mode** instruction from the **+** menu first. The prompt points v0 at the Quickstart through the Docs server instead of its memory, and pins the decisions agents most often get wrong.

Prompt for v0

```text
Install Amplitude analytics in this Next.js app.

Before writing code:
1. Use the Amplitude Docs MCP server. Get the page
   "get-started/amplitude-quickstart" and use the npm install path it
   recommends for browser apps. Then get
   "sdks/frameworks/nextjs-installation-guide" for where init belongs in
   the App Router. Do not pick a package from memory.
2. Use the Amplitude MCP server. List my Amplitude projects and ask me
   which project this app should send to.
3. Show me your plan before editing files.

Then:
- Read the API key from process.env.NEXT_PUBLIC_AMPLITUDE_API_KEY. It is
  already set in the project's environment variables. Never hardcode the
  key.
- Create lib/amplitude.ts as a "use client" module. Call initAll there
  exactly once, and only in the browser: guard it with
  typeof window !== "undefined", because pages render on the server.
  Export a component that renders null and render it once from
  app/layout.tsx so the module loads on every page. Do not call initAll
  in a page, a component body, or a useEffect.
- Set sessionReplay.sampleRate to 1 and tell me that session replay is on
  and how to turn it off.
- Rely on autocapture for page views. Do not add manual page view tracking.
- If the app has login, call setUserId with the signed-in user's ID after
  login, and call reset() only on logout.
- Do not add any custom events yet.

When you finish, list every file you changed and why.
```

v0 comes back with the docs pages it read, a project question, and a plan. Pick the project, approve the plan, and let it build.

## 4. Review what v0 changed

Review the diff before you test. Open the **Diff** tab on the message where v0 made the change; it shows every line that version added or removed. If the change went sideways, the version controls on that message let you restore the previous version. These are the mistakes that show up most often, and each takes seconds to spot:

1. **Package.** For browser apps installed from npm, the Quickstart recommends `@amplitude/unified`. Anything else deserves a question.
2. **API key.** Search the code for the literal key. It should appear nowhere in the source, only in the project's environment variables.
3. **Server rendering.** Next.js renders pages on the server first. `initAll` must sit behind a `typeof window !== "undefined"` check in a `"use client"` module, or the server tries to run browser-only code.
4. **Init location.** One `initAll` call, in `lib/amplitude.ts`, loaded once from `app/layout.tsx`. Not inside a page, a component body, or a `useEffect`.
5. **Duplicate page views.** No hand-written `track("Page Viewed")` next to autocapture, which tracks page views by default.
6. **Logout.** `reset()` runs on logout only. Calling it on every render or auth check gives each visitor a new device ID on every load.
7. **Session replay.** `@amplitude/unified` records sessions when `sessionReplay.sampleRate` is above 0. Keep it, or set it to `0` on purpose.

A correct init file follows the pattern in the [Next.js installation guide](https://amplitude.com/docs/sdks/frameworks/nextjs-installation-guide):

lib/amplitude.ts

```typescript
"use client";

import * as amplitude from "@amplitude/unified";

async function initAmplitude() {
  await amplitude.initAll(process.env.NEXT_PUBLIC_AMPLITUDE_API_KEY!, {
    analytics: {
      autocapture: true,
    },
    sessionReplay: {
      sampleRate: 1, // set to 0 to turn session replay off
    },
  });
}

if (typeof window !== "undefined") {
  initAmplitude();
}

export const Amplitude = () => null;

export default amplitude;
```

`app/layout.tsx` imports `Amplitude` from that file and renders `<Amplitude />` once, which loads the module on every page without turning the layout into a client component.

If the app has login, the identity calls belong in the client code that runs after sign-in and sign-out succeed:

in a client component

```typescript
import amplitude from '@/lib/amplitude';

// after a successful sign-in
amplitude.setUserId(user.id);

// after a successful sign-out
amplitude.reset();
```

**Why.** The user ID must be a string of at least 5 characters, or Amplitude drops it from the event. Auth providers that issue UUIDs clear that easily; integer database IDs like `42` don't, so prefix them, for example `user-42`, and use the same format anywhere else you send events.

If something fails the review, ask v0 to fix it in the same chat:

Prompt for v0

```text
Move the Amplitude init out of the page component into lib/amplitude.ts,
mark that file "use client", guard initAll with
typeof window !== "undefined", render its Amplitude component once from
app/layout.tsx, and read the key from
process.env.NEXT_PUBLIC_AMPLITUDE_API_KEY instead of the literal string.
List the files you changed.
```

## 5. Add an event that matches your taxonomy

This is where the Amplitude MCP server earns its setup. Ask v0 to check what already exists in Amplitude before it names anything.

Prompt for v0

```text
I want to track when a user exports a report, with the export format as
a property.

1. Use the Amplitude MCP server to list the existing events and event
   properties in the project we picked.
2. If an event for this already exists, use its exact name and property
   names. If not, propose a name that matches the casing of the existing
   events, and wait for me to confirm it.
3. Import track from "@amplitude/unified" and add one track call in the
   client component's export handler, after the export succeeds, not in a
   render or an effect. If the export runs in a Server Action, call track
   in the client after the action resolves.
```

If your tracking plan uses Title Case with spaces, v0 should propose `Report Exported`, not `reportExported` or `report_exported`. Once you confirm, it adds a single call in the handler:

components/export-button.tsx (inside the click handler, after the export succeeds)

```typescript
import { track } from "@amplitude/unified";

track("Report Exported", { format });
```

**Why.** `track` from `@amplitude/unified` runs in the browser. Server Actions and route handlers run on the server, where the browser SDK can't send anything, so the call goes in the client component that started the action.

**MCP.** V0 can also add the new event to your tracking plan through the Amplitude MCP server, if your Amplitude role has the **Use MCP (write)** permission and the Update Tracking Plan permission in Amplitude Data. Ask it to create the event in the tracking plan, so the plan knows about `Report Exported` before the first one arrives.

## Verify it worked

Open the preview, sign in if your app has login, export a report, then check in this order:

1. **Network tab.** Open your browser's DevTools on the v0 tab, filter the Network tab for `api2.amplitude.com`, and look for a `POST` to `/2/httpapi` returning `200`. Requests from the preview frame show up there too.
2. **Ingestion Debugger.** In Amplitude, click **Data**, select **Sources**, then open the **Ingestion Debugger** tab. The successful requests and the events and identify counts charts should show your uploads.
3. **User Profiles.** Go to **Users > User Profiles** and search your user ID or device ID. `[Amplitude] Page Viewed` and `Report Exported` appear in the event stream within ten seconds to a minute. Click `Report Exported` to confirm the `format` value.
4. **Ask v0.** With the Amplitude MCP server connected, ask it to check the data for you:

Prompt for v0

```text
Using the Amplitude MCP server, look up my user profile in this project
and tell me whether "Report Exported" arrived in the last hour and which
format values it has.
```

After you publish, repeat step 1 on the published app's URL. It's a separate build, so it's worth confirming the key made it into Production.

## Troubleshooting

### No requests to api2.amplitude.com in the preview

The key is undefined in the browser. Confirm the variable is named `NEXT_PUBLIC_AMPLITUDE_API_KEY` with the prefix, that it's applied to the Development environment, and that it isn't marked sensitive. If you added it after the preview started, ask v0 to restart the dev server. An ad blocker can also drop the requests; test once with it turned off.

### Events arrive from the preview but not from the published app

The key isn't applied to Production, or you added it after your last publish. Next.js bakes `NEXT_PUBLIC_` values in at build time, so apply the variable to Production and publish again.

### The preview shows "window is not defined"

`initAll` runs during server rendering. Move it into `lib/amplitude.ts`, mark the file `"use client"`, and keep the call behind the `typeof window !== "undefined"` check from step 4.

### v0 installed a different package than the Quickstart names

It skipped the docs lookup. Ask it to get `get-started/amplitude-quickstart` through the Amplitude Docs MCP server and redo the install from that page.

### Events show in the Network tab but not in your project

The key belongs to a different project than the one you picked, or it's an EU project sending to the US endpoint. Compare the key in your environment variables with Settings > Projects > your project > General, and set `serverZone: "EU"` in `initAll` for EU projects.

### v0 says it has no Amplitude tools, or OAuth never finishes

Open **+** > **MCPs** and check that both servers exist and are enabled. During OAuth, sign in to only one Amplitude organization; signing in to several can break authentication. If it still fails, remove the Amplitude server and add it again.

## Save the rules as a v0 Instruction

v0 keeps reusable rules as **Instructions**, saved to your account and available in every chat and project. Create one so the next time you ask v0 to track something it follows these conventions without the long prompt:

1. Click the **+** button in the prompt bar.
2. From **Instructions**, select **New Instruction**.
3. Set **Title** to `Amplitude analytics` and paste this as the **Rule**, then click **Add**.

Prompt for v0

```text
Analytics (Amplitude)
- Look up Amplitude SDK usage with the Amplitude Docs MCP server before
  writing analytics code. Never install or import Amplitude packages from
  memory.
- Before adding a track call, list existing events with the Amplitude MCP
  server and reuse existing event and property names. Match the existing
  casing. Ask before creating a new event name.
- The SDK is initialized once in lib/amplitude.ts, a "use client" module,
  behind typeof window !== "undefined", and loaded from app/layout.tsx.
  Never call initAll anywhere else.
- The API key is NEXT_PUBLIC_AMPLITUDE_API_KEY in the project's
  environment variables. Never hardcode it.
- Page views come from autocapture. Never add manual page view tracking.
- Call setUserId with the auth user ID after sign-in and reset() only on
  sign-out.
- Track user actions in client event handlers after the action succeeds,
  not in effects, render paths, or Server Actions.
- Import track from "@amplitude/unified".
```

An Instruction applies only while it's checked. Check **Amplitude analytics** from the **+** menu in any chat where you'll touch analytics code, and it stays on for your messages until you uncheck it. Instructions live on your account, so teammates working in the same project need to add their own.

## What this unlocks

- [Session replay](https://amplitude.com/session-replay), with `sampleRate` above 0, lets you watch the session where `Report Exported` fired, or the one where someone opened the export menu and gave up.
- [Heatmaps](https://amplitude.com/heatmaps), built from those same session replays, show where people clicked on the reports page before they exported.
- [Feature Experiment](https://amplitude.com/amplitude-experiment) can test a new export flow with `Report Exported` as the success metric, and the `experiment()` client is already inside `@amplitude/unified`.
- [Guides and surveys](https://amplitude.com/guides-and-surveys) can point people who view reports but never fire `Report Exported` to the export button.

One integration; everything else reads from the same events.

## Next steps

[Web frameworksAdd product analytics to a Next.js appWhat the correct App Router install looks like, file by file, so you can check v0's work against it.](/build/nextjs-product-analytics)[AI coding toolsAdd product analytics to your app with LovableThe same workflow in another chat-first app builder, with the rules saved as project knowledge.](/build/lovable-product-analytics)[AI coding toolsAdd product analytics to your app with Claude CodeThe same workflow in a terminal agent, with the rules saved in CLAUDE.md.](/build/claude-code-product-analytics)

Reference docs

[Connect Amplitude MCP to other clients →](https://amplitude.com/docs/amplitude-ai/amplitude-mcp/other-clients)[Amplitude MCP server →](https://amplitude.com/docs/amplitude-ai/amplitude-mcp)[Docs MCP server →](https://amplitude.com/docs/amplitude-ai/docs-mcp-server)[Amplitude Quickstart →](https://amplitude.com/docs/get-started/amplitude-quickstart)[Next.js installation guide →](https://amplitude.com/docs/sdks/frameworks/nextjs-installation-guide)[Debug analytics →](https://amplitude.com/docs/analytics/debug-analytics)

Amplitude is the leading [all-in-one analytics platform](https://amplitude.com/) for building better products. Product and engineering teams use Amplitude to connect [product analytics](https://amplitude.com/amplitude-analytics) and [web analytics](https://amplitude.com/web-analytics) with [session replay](https://amplitude.com/session-replay), [heatmaps](https://amplitude.com/heatmaps), [experimentation](https://amplitude.com/amplitude-experiment), [feature flags](https://amplitude.com/feature-management), and [guides and surveys](https://amplitude.com/guides-and-surveys) in one unified workflow, with [AI agents](https://amplitude.com/ai-agents) working across all of it. Learn how Amplitude is building [self-improving products](https://amplitude.com/self-improving-products) with [Wave](https://amplitude.com/wave), helping teams turn product data into PRs.

For agents

[View raw .md](/build/v0-product-analytics.md)[llms.txt](/llms.txt)

## Ship the instrumentation, then read the data

Once events are flowing, Amplitude turns them into funnels, retention curves, and session replays without any further setup.

[Create a free account](https://app.amplitude.com/signup)[Browse all Build tutorials](https://amplitude.com/build)
