# Astro

Add ProductLense to the base layout of an Astro site with an is:inline script, then identify users from a small component.

In Astro, add the script to the base layout that every page uses. Mark it `is:inline` so Astro leaves the tag exactly as written instead of bundling it. Sites that use Astro's client router (view transitions) are recorded through the history API.

## Add the script

Replace `SITE_ID` with the id from Settings → Sites in the ProductLense dashboard.

```astro title="src/layouts/Layout.astro" {8-9}
---
const { title } = Astro.props;
---
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>{title}</title>
    <script is:inline>window.productlense=window.productlense||function(){(window.productlense.q=window.productlense.q||[]).push(arguments)}</script>
    <script is:inline defer data-site="SITE_ID" src="https://api.productlense.app/a.js"></script>
  </head>
  <body>
    <slot />
  </body>
</html>
```

> [!IMPORTANT]
> Without `is:inline`, Astro processes the script tag as a module and drops `data-site`. The ProductLense script must stay a classic script because it reads its settings from its own tag.

With the client router, the script loads once and stays loaded across navigations, recording one pageview per route change. No `data-astro-rerun` attribute is needed.

## Identify users

On pages rendered with a signed-in user (server output or hybrid rendering), pass the user id to a small component:

```astro title="src/components/ProductLenseIdentify.astro" {4-5}
---
const { userId } = Astro.props;
---
<script is:inline define:vars={{ userId }}>
  if (userId) window.productlense('identify', String(userId));
</script>
```

```astro title="src/pages/dashboard.astro"
<ProductLenseIdentify userId={Astro.locals.user?.id} />
```

The queue stub in the layout makes `window.productlense` callable before the deferred script has loaded. Use the same id you store on the customer in your billing provider; see [how payments are attributed](/docs/revenue/attribution).

## Custom events

```html
<script>
  document.querySelector('#upgrade')?.addEventListener('click', () => {
    window.productlense('event', 'Upgrade clicked', { plan: 'growth' });
  });
</script>
```

See [custom events](/docs/track/custom-events) for naming rules.

## Verify your installation

1. Build and deploy, then open your site in a normal browser window.
2. Open the Live page in the ProductLense dashboard. Your visit appears within a few seconds.
3. In the browser's developer tools, the Network tab shows a `POST` to `https://api.productlense.app/api/e` with status `204`.

`astro dev` runs on `localhost`, where nothing is sent unless you add `data-dev="true"` to the tag. Ad blockers in your own browser may block the request. If the visit does not appear, follow [Verify your installation](/docs/install/verify).
