---
title: "How to add heatmaps to an Astro site"
description: "Record session replay in an Astro site so Amplitude heatmaps map clicks per page, give each tab its own URL, and create your first heatmap."
canonical: "https://amplitude.com/en-us/build/astro-heatmaps"
---

# How to add heatmaps to an Astro site

Record session replay in an Astro site so Amplitude heatmaps map clicks per page, give each tab its own URL, and create your first heatmap.

Source: https://amplitude.com/en-us/build/astro-heatmaps

---

# How to add heatmaps to an Astro site

Confirm session replay records in an Astro site, switch on heatmap capture for the project, give each settings tab its own page so heatmaps don't merge them, and create a click map for a dynamic route. About 15 minutes of setup, then heatmaps fill in as traffic arrives.

- Astro 6+
- Static or on-demand
- Unified SDK 1.x
- 15 min

Chris Tam · Last updated 19 October 2026

Astro turns every file in `src/pages/` into its own URL. [Heatmaps](https://amplitude.com/heatmaps) show where people click and how far they scroll on each of those pages, so you see which parts of a page get used and which get skipped.

In this tutorial, you'll confirm session replay, which heatmaps are built from, give each settings tab its own page, and create your first heatmap. It builds on [the Astro product analytics page](/build/astro-product-analytics).

## What you'll build

An Astro site that records session replay on every page, with or without `<ClientRouter />`, sends `[Amplitude] Page Viewed` with the same `device_id` as the replay, keeps any masking rules from the session replay page, and gives the Profile and Billing tabs of `/settings` their own pages, plus a click map in Amplitude for every `/projects/[projectId]` page. By the end you'll see a replay of your test session and a heatmap set up to fill in once traffic crosses the data threshold.

## Prerequisites

- An Astro 6 or later project with TypeScript. Astro 6 needs Node.js 22.12 or later, and Astro 7.4 and later need 22.22 or later.
- The setup from [How to add product analytics to an Astro site](/build/astro-product-analytics): `initAll` in `src/scripts/amplitude.ts`, loaded by `<Amplitude />` in `src/layouts/Layout.astro`, plus the `/projects/new` page.
- Either output mode works. Pages are prerendered by default; step 4 shows what changes for a dynamic route rendered on demand.
- An Amplitude project API key. In Amplitude, go to Settings > Projects > your project > General.
- Access to heatmaps in Amplitude. Any user with View permissions can create a heatmap; turning on heatmap capture for a project takes an Admin or Manager role.

Heatmaps are available on the Plus, Growth, and Enterprise plans, for customers with session replay; [compare plans](https://amplitude.com/pricing). No Amplitude account yet? [Sign up for free](https://app.amplitude.com/signup) to get your project API key.

Amplitude recommends a separate development project for testing heatmaps, so your test clicks stay out of production data. Heatmap and session replay events don't count toward your event volume.

## 1. Install the SDK

The [Quickstart](https://amplitude.com/docs/get-started/amplitude-quickstart) installs `@amplitude/unified` for browser apps that use npm. It bundles analytics, session replay, Feature Experiment, and guides and surveys behind one `initAll` call, and Amplitude keeps the `device_id` on replay and analytics events aligned for you, which heatmap segment and cohort filters depend on. If you followed the [Astro product analytics page](/build/astro-product-analytics), it's already installed and `.env` holds `PUBLIC_AMPLITUDE_API_KEY`; skip to step 2. Otherwise install it, then add the key to `.env` as that page's step 1 shows.

Terminal

```sh
npm install @amplitude/unified
```

Already on `@amplitude/analytics-browser` to keep bundle size down? Add the [Session Replay Browser SDK Plugin](https://amplitude.com/docs/sdks/session-replay/session-replay-plugin) to your existing init instead of installing a second SDK. It takes the options from the `sessionReplay` block of your `initAll` call, plus `serverZone`, which `initAll` sets at the top level.

Heatmaps need Session Replay Browser SDK Plugin 1.7.0 or later. The Verify section shows how to read the version your page actually runs.

## 2. Confirm session replay is on

No code change. Session replay's default sample rate is 0, which records nothing, and recording is what heatmaps are built from. The base page's `sessionReplay.sampleRate: import.meta.env.DEV ? 1 : 0.01` in `src/scripts/amplitude.ts` already sets it above 0, which is all heatmaps need, so keep that file as it is, with every line other Astro pages added to it. Before you raise the rate, add the masking from [the Astro session replay page](/build/astro-session-replay), because heatmap backgrounds are replay snapshots and unmasked text shows up in them.

Session replay follows both ways an Astro site navigates. Without `<ClientRouter />`, every link is a full page load: `src/scripts/amplitude.ts` runs again, session replay takes a fresh snapshot of the new page, and the session carries over because the SDK keeps it in browser storage. With `<ClientRouter />`, the module runs once per visit, the router swaps the `<body>` in place, and session replay records the swap as DOM changes while autocapture picks up the new URL. Either way, each page has its own URL, which is what heatmaps group by.

**Why.** Initializing more than once can leave replay and analytics events with different device or session IDs. Heatmaps still draw an unsegmented map in that case, but segment and cohort filters come back empty, because Amplitude can't join the clicks to your users. Astro includes a component's `<script>` once per page, so `<Amplitude />` gives you one init per page load. Never call `initAll` a second time, for example in a React, Vue, or Svelte island that imports `@amplitude/unified` directly, or in an `astro:page-load` listener. Islands import from `src/scripts/amplitude.ts`, and nothing imports the SDK in component frontmatter, middleware, or endpoints, which run on the server or at build time.

You don't need `elementInteractions` for heatmaps. The heatmap prerequisites list session replay, not click autocapture; the clicks on the map come from session replay, once heatmap capture is on for the project (step 3). The base page turns `elementInteractions` on for click events in product analytics, so it stays. `pageUrlEnrichment` is on by default with autocapture, so the base file doesn't list it; leave it on. It adds `[Amplitude] Page URL` to your own `track` events, so you can chart them per page next to the heatmap.

Be deliberate about the sample rate. Every heatmap reflects only the sessions you captured, so at `0.01` a map is built from 1% of traffic and takes longer to cross the data threshold. Amplitude recommends starting low and raising the rate over a few days; capture stops for the month once your org's replay quota runs out. Session Replay Settings in Amplitude can also set the project's rate remotely, so check there when the rate you see doesn't match your code.

Unified also initializes guides and surveys by default. If you won't use them, add `engagement: { skip: true }` to the `initAll` options, as the [Unified SDK docs](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk) describe.

## 3. Turn on heatmap capture in Amplitude

The SDK records replays, but the project decides whether heatmap data gets collected. In Amplitude, go to Settings > Organizational Settings > Session Replay Settings. The project list shows a session capture toggle and a heatmap capture toggle for each project. Turn both on for this project.

Select the project to open its Sampling control. A rate set there applies to the project without a deploy, which is the easier place to raise capture once heatmaps need more data.

## 4. Give each tab its own page

Heatmaps compute data per URL string, not per view. A tab bar that shows and hides panels with a script never changes the URL, so the Profile and Billing tabs of `/settings` end up in one heatmap, drawn over whichever tab the background happened to catch. Script-driven tab components work this way. Astro's fix is file-based routing: each tab becomes its own page under `src/pages/settings/`, and a small component renders the tab bar on both.

src/components/SettingsTabs.astro

```html
---
const tabs = [
  { href: "/settings/profile", label: "Profile" },
  { href: "/settings/billing", label: "Billing" },
];
// Prerendered builds report the path with a trailing slash; compare without it.
const current = Astro.url.pathname.replace(/\/$/, "");
---

<h1>Settings</h1>
<nav>
  {
    tabs.map((tab) => (
      <a href={tab.href} aria-current={current === tab.href ? "page" : undefined}>
        {tab.label}
      </a>
    ))
  }
</nav>
```

src/pages/settings/profile.astro

```html
---
import Layout from "../../layouts/Layout.astro";
import SettingsTabs from "../../components/SettingsTabs.astro";
---

<Layout>
  <main>
    <SettingsTabs />
    <h2>Profile</h2>
  </main>
</Layout>
```

src/pages/settings/billing.astro

```html
---
import Layout from "../../layouts/Layout.astro";
import SettingsTabs from "../../components/SettingsTabs.astro";
---

<Layout>
  <main>
    <SettingsTabs />
    <h2>Billing</h2>
  </main>
</Layout>
```

If the Billing tab shows account data, put it in a container with the `data-amp-mask` attribute from [the Astro session replay page](/build/astro-session-replay). Heatmaps still record the clicks, and the background shows masked text:

```html
<h2>Billing</h2>
<div data-amp-mask>
  <!-- account data -->
</div>
```

If you use `MASKED_PATHS` from the session replay page, add `"/settings/billing"` to it instead; its `["/billing"]` default doesn't cover this path.

If your settings pages render on demand, add `export const prerender = false;` to the frontmatter of all three files in `src/pages/settings/`, including `index.astro`, so the server answers `/settings` with a redirect instead of a meta-refresh page.

Send `/settings` on its own to the first tab, so it never becomes a page of its own:

src/pages/settings/index.astro

```html
---
// Prerendered: Astro writes a page that redirects at once with a meta refresh.
// Rendered on demand: the server answers with a 301.
return Astro.redirect("/settings/profile", 301);
---
```

Link your navigation and the tab bar straight to `/settings/profile` and `/settings/billing`. The redirect is there for typed URLs and old bookmarks. Pass 301: with the default 302, a prerendered build writes a page that waits 2 seconds before it redirects, and the Back button keeps returning to it. `npm run dev` always answers with a server redirect, so check the prerendered behavior with `npm run preview`.

The heatmap in step 5 targets a dynamic project route. If your site doesn't have a project page yet, add a minimal one:

src/pages/projects/\[projectId].astro

```html
---
import Layout from "../../layouts/Layout.astro";

// Prerendered (the default): Astro builds one page per entry. Return your
// real project IDs here, as strings. Rendered on demand: delete this function
// and add `export const prerender = false;` instead.
export function getStaticPaths() {
  return [
    { params: { projectId: "demo-project" } },
    { params: { projectId: "launch-plan" } },
  ];
}

const { projectId } = Astro.params;
---

<Layout>
  <main>
    <h1>Project {projectId}</h1>
  </main>
</Layout>
```

Rendered on demand, the route answers every ID, so a mistyped or stale ID still gets a page and its clicks land in the step 5 map. Look the project up and `return new Response(null, { status: 404 });` when it doesn't exist.

`src/pages/projects/new.astro` from the product analytics page keeps working: Astro gives a static route precedence over a dynamic one, so `/projects/new` never reaches `[projectId].astro`. None of these files import the SDK; `<Amplitude />` in your layout covers them, and its identity element keeps running on every tab.

Now `/settings/profile` and `/settings/billing` get separate heatmaps, and each tab switch also sends its own `[Amplitude] Page Viewed`, as a full page load or a `<ClientRouter />` navigation.

**Why.** Put the tab in the path, not in a query string such as `/settings?tab=billing` read with `Astro.url.searchParams`. Heatmaps need the `[Amplitude] Page URL` property to match URLs, and that property is the page URL with query parameters removed, so `/settings?tab=profile` and `/settings?tab=billing` can land in the same heatmap. A path segment is unambiguous. Modals and drawers that don't change the URL also merge into the page underneath; if one matters, give it a page the same way.

Watch trailing slashes. Heatmap data is keyed by the URL string, so `/settings/billing` and `/settings/billing/` are two URLs. Astro's dev server and pages rendered on demand match both by default (`trailingSlash: 'ignore'`), and prerendered pages are built as `settings/billing/index.html`, so whether a visitor ends up on the slash form depends on your host, not on Astro. Write links in one form, set `trailingSlash` in `astro.config.mjs` to match what your host serves, and keep it that way once heatmaps are collecting.

## 5. Create your first heatmap

Heatmaps appear after Amplitude collects enough replay click data across your site: at least 10 separate pages, with about 500 tracked replay clicks on each page. These thresholds are approximate. Create the heatmap now and it fills in once traffic crosses them.

1. In Amplitude, click Heatmaps in the left navigation, then + New Heatmap.
2. Choose a click map. You can change the map type at any time.
3. Select the URL. `[projectId].astro` gives every project its own URL, so use Pattern match with `https://your-domain.com/projects/*` to combine them into one map. That pattern also matches `/projects/new` from the product analytics page, so the new-project form's clicks land in the same map. Keep that in mind when you read it, or move the form to a path outside `/projects/` if you want project pages mapped on their own. Use Exact match for a single page, such as `https://your-domain.com/settings/billing`, written in the trailing-slash form your live site uses, and Starts with for a section, such as `https://your-domain.com/settings`.
4. Optionally pick a segment of users by user property or cohort.
5. Pick a device type. Heatmaps group data into four screen-width buckets: greater than 1440px, 900 to 1440px, 500 to 899px, and less than 500px. A responsive layout that collapses its nav into a menu below a CSS breakpoint looks different in each bucket, and the background and the click data must fall in the same one.
6. Choose a background. Each heatmap generates eight, taken from the page states with the most actions. Skip any that caught an open modal or a loading state.

Once your data meets the thresholds, Amplitude also creates a few heatmaps automatically for your highest-traffic pages. You can delete them; they aren't recreated.

If your routes carry personal data in the path, such as an email address in `src/pages/users/[email].astro`, configure URL filter rules (`ugcFilterRules` inside `interactionConfig`, with `enabled: true`; see [Filter sensitive URL content](https://amplitude.com/docs/session-replay/configure-ugc-filter-rules)) to replace those URLs before session replay and heatmaps record them.

**MCP.** Working in Cursor or Claude Code? [Amplitude's MCP server](https://amplitude.com/docs/amplitude-ai/amplitude-mcp) lets your agent read your project's existing event taxonomy before it adds `track` calls near a heatmap hotspot, so new events match names you already use instead of inventing `planUpgraded` next to `Plan Upgraded`.

## Verify it worked

A development session can't reach the heatmap data threshold, so verification stops at confirming that replays arrive from a new enough SDK and that each tab has its own URL. Run `npm run dev`, open `http://localhost:4321/settings/profile` in a fresh window, switch to the Billing tab, then type `/projects/demo-project` in the address bar. Check in this order:

1. **Network tab.** Filter for `amplitude`. You should see a POST to `api2.amplitude.com` returning 200, a request to `sr-client-cfg.amplitude.com`, and replay uploads to `api-sr.amplitude.com`. None of them come from the build or the server render; they start once `src/scripts/amplitude.ts` runs in the browser.
2. **Ingestion Debugger.** In Amplitude, click Data, select Sources, then open the Ingestion Debugger tab. The successful requests chart should show your uploads. It shows counts, not individual events.
3. **User lookup.** Go to Users > User Profiles and search your `user-` prefixed test ID, or your device ID (the [Instrumentation Explorer](https://amplitude.com/docs/analytics/debug-analytics#instrumentation-explorer) Chrome extension shows it as `device_id`) if you aren't signed in. Within ten seconds to a minute, the event stream shows one `[Amplitude] Page Viewed` per page you visited; click the two settings views and their `[Amplitude] Page URL` ends in `/settings/profile` and `/settings/billing`. A Play Session button appears for the session once the replay is processed, generally about five minutes after the session begins.
4. **Session Replay debug panel.** In the Instrumentation Explorer, turn on the Session Replay debug panel. It shows the current replay ID, the session replay SDK and plugin versions, the sample rate, and the masking settings. The plugin version must be 1.7.0 or later, and the sample rate must not be 0.
5. **Heatmaps.** Open the heatmap from step 5. In a development project it shows "No heatmap available" until the thresholds are met.

Check a production build too, because prerendered pages behave differently there: run `npm run build` and `npm run preview`, open `/settings` and confirm it lands on `/settings/profile`, and open `/projects/demo-project`. The production build records about 1% of sessions, so your preview session probably isn't recorded; that's expected. After you deploy, open a settings tab on the live site and read `[Amplitude] Page URL` on its page view in the Instrumentation Explorer. That's the exact form, with or without a trailing slash, to use in Exact match filters. Also confirm the live site serves the updated SDK, not only your local build.

## Troubleshooting

### The heatmap is blank or says "No heatmap available"

Work through the causes in order: Amplitude is still processing new replay data (a few minutes after install), the URL filter doesn't match URLs in your events (check the trailing slash), the deployed site runs a session replay plugin older than 1.7.0, or traffic hasn't reached about 500 replay clicks on each of 10 pages. If `[Amplitude] Page URL` was hidden, restore it in Data > Properties.

### Every tab on a page shows up in one heatmap

The tabs share a URL. Move each one to its own page under `src/pages/settings/` as in step 4. A tab kept in a query string can merge too, because `[Amplitude] Page URL` drops query parameters; move it into the path.

### One page's clicks are split across two URLs

Some visits land on `/settings/billing` and others on `/settings/billing/`. Write every link in one form, set `trailingSlash` in `astro.config.mjs` to match your host, and use Starts with in the heatmap to combine both forms in one map.

### The build fails on `src/pages/projects/[projectId].astro`, or a project page returns 404

A prerendered dynamic route needs `getStaticPaths()`, and Astro builds only the IDs it returns. Return every project ID as a string, or render the route on demand with `export const prerender = false;` and an adapter, and delete `getStaticPaths()`.

### No replays at all, even with a sample rate of 1

Check the project's rate and capture toggles in Session Replay Settings (step 3). Then open the console. If you send a Content-Security-Policy from middleware, your adapter, or your host, a blocked request appears there. Allow the Amplitude hosts listed in [step 5 of the Astro session replay page](/build/astro-session-replay#5-allow-amplitude-in-your-csp), which follows the [CSP guidance in the docs](https://amplitude.com/docs/sdks/guides-and-surveys/sdk#content-security-policy-csp); unified also loads guides and surveys, which need `https://*.amplitude.com` in more directives than `connect-src`. If remote configuration fails to load, session replay captures nothing, on purpose. An ad blocker also stops capture; test in a clean profile.

### A background shows no data

The background's viewport width falls in a different screen-width bucket from your recorded sessions. Use Change Screenshot > From a Replay and pick a background captured at a width where your data exists.

### Segment or cohort filters return nothing

Replay and analytics events carry different `device_id` values, so Amplitude can't join clicks to users. Look for a second `initAll` or `init` call, for example in an island that imports `@amplitude/unified` instead of `src/scripts/amplitude.ts`, or a standalone session replay SDK running beside your analytics. Keep the single init in `src/scripts/amplitude.ts`.

### "Heatmaps isn't available for your organization"

Your organization predates Amplitude's current packaging and needs manual enablement. Contact Amplitude Support.

## Full code reference

Every file this tutorial adds, in one block: the version to hand to an agent. 5 files, 78 lines. None of them is a shared file, so add them as they are.

5 files, 78 lines

```html
// -- src/components/SettingsTabs.astro --
---
const tabs = [
  { href: "/settings/profile", label: "Profile" },
  { href: "/settings/billing", label: "Billing" },
];
// Prerendered builds report the path with a trailing slash; compare without it.
const current = Astro.url.pathname.replace(/\/$/, "");
---

<h1>Settings</h1>
<nav>
  {
    tabs.map((tab) => (
      <a href={tab.href} aria-current={current === tab.href ? "page" : undefined}>
        {tab.label}
      </a>
    ))
  }
</nav>

// -- src/pages/settings/profile.astro --
---
import Layout from "../../layouts/Layout.astro";
import SettingsTabs from "../../components/SettingsTabs.astro";
---

<Layout>
  <main>
    <SettingsTabs />
    <h2>Profile</h2>
  </main>
</Layout>

// -- src/pages/settings/billing.astro --
---
import Layout from "../../layouts/Layout.astro";
import SettingsTabs from "../../components/SettingsTabs.astro";
---

<Layout>
  <main>
    <SettingsTabs />
    <h2>Billing</h2>
  </main>
</Layout>

// -- src/pages/settings/index.astro --
---
// Prerendered: Astro writes a page that redirects at once with a meta refresh.
// Rendered on demand: the server answers with a 301.
return Astro.redirect("/settings/profile", 301);
---

// -- src/pages/projects/[projectId].astro --
---
import Layout from "../../layouts/Layout.astro";

// Prerendered (the default): Astro builds one page per entry. Return your
// real project IDs here, as strings. Rendered on demand: delete this function
// and add `export const prerender = false;` instead.
export function getStaticPaths() {
  return [
    { params: { projectId: "demo-project" } },
    { params: { projectId: "launch-plan" } },
  ];
}

const { projectId } = Astro.params;
---

<Layout>
  <main>
    <h1>Project {projectId}</h1>
  </main>
</Layout>

// Unchanged from earlier pages; keep your versions: .env, src/scripts/amplitude.ts, src/layouts/Layout.astro, src/components/Amplitude.astro, src/components/SignOutButton.astro, src/components/CreateProjectForm.astro, src/middleware.ts, src/env.d.ts, src/lib/auth.ts, src/pages/projects/new.astro, src/pages/index.astro.
```

## Hand it to your agent

Prefer to have Cursor, Claude Code, or Codex CLI do the wiring? This prompt points the agent at this page and pins the decisions that matter.

Using Cursor or Claude Code? Paste this prompt

```text
Complete https://amplitude.com/build/astro-product-analytics first, or
confirm this Astro site already has its setup: src/scripts/amplitude.ts,
src/components/Amplitude.astro rendered in src/layouts/Layout.astro, the
src/lib/auth.ts stub, and src/pages/projects/new.astro. Create any that are
missing. Then set up Amplitude heatmaps by following
https://amplitude.com/build/astro-heatmaps exactly. Merge into existing
shared files and never delete lines another Amplitude Build page added;
each file's first comment names them. Don't change src/scripts/amplitude.ts:
confirm it calls @amplitude/unified initAll once at the top level with a
sessionReplay sampleRate above 0 (import.meta.env.DEV ? 1 : 0.01), and never
add a second initAll in an island, an astro:page-load listener, component
frontmatter, middleware, or an endpoint. Tell me how to turn session replay
off, and tell me to add the masking from
https://amplitude.com/build/astro-session-replay before I raise the rate.
Find every page that switches tabs with a script or a query string and give
each tab its own page, as the page does for settings:
src/components/SettingsTabs.astro, src/pages/settings/profile.astro,
src/pages/settings/billing.astro, and src/pages/settings/index.astro
returning Astro.redirect("/settings/profile", 301), with prerender = false
on all three when the site renders on demand. If the site has no project
page, add src/pages/projects/[projectId].astro with getStaticPaths()
returning string IDs when it's prerendered, or prerender = false with no
getStaticPaths() when it renders on demand, returning a 404 for unknown
IDs. Write every link in one form,
without a trailing slash unless my host serves the slash form, and tell me
which trailingSlash value astro.config.mjs should use. Remind me to turn on
heatmap capture in Session Replay Settings. Don't hardcode the key and don't
invent event names. Report every file you changed.
```

## What this unlocks

- [Session replay](https://amplitude.com/session-replay), already recording from the base page, lets you select an area of a click map and watch the sessions behind those clicks.
- [Product analytics](https://amplitude.com/amplitude-analytics) can chart `[Amplitude] Page Viewed` for `/settings/billing` against your upgrade event to see whether the tab you just mapped converts.
- [Feature Experiment](https://amplitude.com/amplitude-experiment), bundled in `@amplitude/unified`, can test a new billing layout, and a heatmap per variant shows how the clicks moved.
- [Guides and surveys](https://amplitude.com/guides-and-surveys), also bundled, can point users to a button the click map shows they miss.

One integration; everything else reads from the same events.

## Next steps

[Web frameworksHow to add session replay to an Astro siteMask sensitive content and whole sections before you raise the sample rate.](/build/astro-session-replay)[Web frameworksHow to add web analytics to an Astro siteSee which channels send the visitors whose clicks you're mapping.](/build/astro-web-analytics)[Web frameworksHow to add guides and surveys to an Astro sitePoint people to the parts of the page your heatmap shows they skip.](/build/astro-guides-surveys)

Reference docs

[Heatmaps →](https://amplitude.com/docs/heatmaps)[Create a heatmap →](https://amplitude.com/docs/heatmaps/create-a-heatmap)[Troubleshoot heatmaps →](https://amplitude.com/docs/heatmaps/troubleshooting)[Session Replay Browser SDK Plugin →](https://amplitude.com/docs/sdks/session-replay/session-replay-plugin)[Manage Session Replay settings →](https://amplitude.com/docs/session-replay/session-replay-settings)[Amplitude MCP server →](https://amplitude.com/docs/amplitude-ai/amplitude-mcp)

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/astro-heatmaps.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)
