Skip to main content
5 min read

Add Zenovay Analytics to Astro

This guide covers adding Zenovay Analytics to an Astro site: installation, custom event tracking, View Transitions support, and cookieless mode. The tracker loads asynchronously under 1 KB and does not set cookies by default.


Quick Setup (2 minutes)

Add the Zenovay tracking script to your Astro layout and you are done. No npm packages, no build plugins, no configuration files.

Step 1: Get Your Tracking Code

Sign in to your Zenovay dashboard, open Domains, click your site, and copy the script snippet from the Tracking script card on the General page.

Step 2: Add to Layout

Open your main Astro layout file and add the script tag inside <head>:

src/layouts/Layout.astroASTRO
---
// src/layouts/Layout.astro
interface Props {
title: string;
}
const { title } = Astro.props;
---
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>{title}</title>
  <script
    defer
    data-tracking-code="YOUR_TRACKING_CODE"
    src="https://api.zenovay.com/z.js"
  ></script>
</head>
<body>
  <slot />
</body>
</html>

That's it! Zenovay will automatically track page views on every page that uses this layout.

Step 3: Verify Installation

Visit your site in a browser and open the Zenovay dashboard. You should see a real-time visitor appear within seconds.

Replace YOUR_TRACKING_CODE with the code shown on your site's General page under Domains.

Tracking script card showing the script snippet with HTML, React, Next.js, and First-Party tabs
Copy your tracking code from the Tracking script card on your site's General settings page.

Custom Events

Track button clicks, form submissions, and other interactions using the global zenovay function.

Inline Script in Astro Components

src/components/SignupButton.astroASTRO
---
// src/components/SignupButton.astro
interface Props {
plan: string;
}
const { plan } = Astro.props;
---
<button id="signup-btn" data-plan={plan}>
Sign Up for {plan}
</button>

<script>
const btn = document.getElementById('signup-btn');
btn?.addEventListener('click', () => {
  if (window.zenovay) {
    window.zenovay('track', 'signup_click', {
      plan: btn.dataset.plan,
    });
  }
});
</script>

Custom Events in Framework Components

If you use React, Vue, or Svelte islands inside Astro, call window.zenovay directly:

src/components/DownloadButton.tsx (React island)TSX
export default function DownloadButton({ file }: { file: string }) {
const handleClick = () => {
  if (window.zenovay) {
    window.zenovay('track', 'file_download', { file });
  }
};

return <button onClick={handleClick}>Download {file}</button>;
}

SPA Navigation with View Transitions

If you use Astro View Transitions, Zenovay automatically detects client-side route changes and records a new page view for each navigation. No extra configuration needed.

src/layouts/Layout.astro (with View Transitions)ASTRO
---
import { ViewTransitions } from 'astro:transitions';
---
<html lang="en">
<head>
  <ViewTransitions />
  <script
    defer
    data-tracking-code="YOUR_TRACKING_CODE"
    src="https://api.zenovay.com/z.js"
  ></script>
</head>
<body>
  <slot />
</body>
</html>

Zenovay listens for the browser History API (pushState / popstate) so it works with any client-side navigation method, including View Transitions.

Cookieless Mode

For privacy-friendly tracking without cookies or localStorage, add the data-cookieless attribute:

Cookieless trackingHTML
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
data-cookieless="true"
src="https://api.zenovay.com/z.js"
></script>

In cookieless mode, Zenovay uses a server-side hash of the visitor's IP subnet, user agent, and a daily-rotating salt to count unique visitors without storing anything on the client device.

Identify Users

If your Astro site has authenticated areas, identify logged-in users:

Identify a userJavaScript
// After login or on authenticated pages
if (window.zenovay) {
window.zenovay('identify', 'user_123', {
  email: 'user@example.com',
  plan: 'pro',
});
}

Track Goals and Revenue

Goals and revenue trackingJavaScript
// Track a conversion goal
if (window.zenovay) {
window.zenovay('goal', 'newsletter_signup', { source: 'footer' });
}

// Track revenue
if (window.zenovay) {
window.zenovay('revenue', 49.99, 'USD');
}

TypeScript Support

Add type declarations so TypeScript recognizes window.zenovay:

src/env.d.tsTypeScript
/// <reference types="astro/client" />

declare global {
interface Window {
  zenovay?: (...args: any[]) => void;
}
}

Content Collections (Blog Analytics)

If you are using Astro Content Collections for a blog, every post automatically gets tracked as long as it renders through your layout. You can add post-specific metadata to events:

src/pages/blog/[...slug].astroASTRO
---
import { getCollection } from 'astro:content';
import Layout from '../../layouts/Layout.astro';

export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({
  params: { slug: post.slug },
  props: { post },
}));
}

const { post } = Astro.props;
const { Content } = await post.render();
---
<Layout title={post.data.title}>
<article>
  <h1>{post.data.title}</h1>
  <Content />
</article>
</Layout>

Zenovay captures the page URL and title automatically, so each blog post shows up as a separate page in your analytics dashboard.

Next Steps

Your Astro site is now tracking with Zenovay! View your analytics in the dashboard.

Continue learning:

Was this page helpful?