Integration guide
Analytics in Astro
A <script> in your layout loads the SDK on every page. Static sites need nothing else; with view transitions, an Astro event counts each navigation.
Before you start
- Astro 3 or newer.
- Your
site_key, and your domain under Allowed origins.
Installation
1Install the SDK
In Astro, variables available in the browser start with
PUBLIC_.npm install @racoelho/analytics.env PUBLIC_ANALISA_SITE_KEY=YOUR_SITE_KEY2Create the instance in a module
Astro scripts are bundled and run once per page load, even when the module is imported by several components.
src/lib/analytics.ts import { Analytics } from '@racoelho/analytics' // imported by several scripts: Astro bundles it once, so there is one instance export const analytics = new Analytics({ siteKey: import.meta.env.PUBLIC_ANALISA_SITE_KEY, })3Import it in the layout
Use the same layout on every page. The first pageview goes out when the module loads.
src/layouts/Layout.astro --- const { title } = Astro.props --- <html lang="en"> <head> <meta charset="utf-8" /> <title>{title}</title> </head> <body> <slot /> <script> import { analytics } from '../lib/analytics' // with <ClientRouter /> (view transitions): count each navigation document.addEventListener('astro:page-load', () => analytics.pageview()) </script> </body> </html>
Events and goals
In any .astro component, a <script> imports the same instance and calls track(name, properties).
<button id="signup">Sign up</button>
<script>
import { analytics } from '../lib/analytics'
// delegated on document: keeps working after view transitions
document.addEventListener('click', (event) => {
if (event.target instanceof Element && event.target.closest('#signup')) {
analytics.track('signup_click', { place: 'hero' })
}
})
</script>Create an event goal named signup_click in the dashboard. For thank-you pages, a path goal is enough.
Page navigation
Without view transitions, each page is a full load and counts itself. With <ClientRouter />, Astro swaps pages without reloading and the SDK does not notice — the astro:page-load listener in the layout covers it (on first load it repeats the pageview, and the SDK drops the duplicate).
Check that it works
- Open the published site in a normal window, with no ad blocker.
- In your browser devtools, Network tab, filter by
v1/i: you should see aPOSTwith status200within 3 seconds (or when you leave the page). - In the dashboard, events show up in about 30 seconds.
- If you use view transitions, navigate between two pages and look for a new
page_view.
Troubleshooting
- With view transitions, clicks stop counting after a navigation
- Bundled scripts run only once; a listener attached to a button is lost when Astro swaps the page content. Listen on
documentand filter by target, as in the example. - The request returns 403 (
origin_not_allowed) - Your domain isn’t in Allowed origins in the site settings. Add the exact origin — with
https://, with and withoutwww, plus test addresses likehttp://localhost:3000if you want to measure in development. - No request shows up in the Network tab
- The SDK honors Do Not Track by default: if your browser sends DNT, nothing is sent. Test in another browser or profile. Ad blockers can also block the script.
- Pageviews show up twice
- The SDK was initialized twice (for example, pasted in the theme and also added by a plugin). Keep a single instance per page.
Create your account and grab the site_key
Free up to 10K events a month, no credit card.
Create a free account