Skip to main content
Virent

Astro Installation Guide

Last researched 2026-08-26

This is the canonical Virent installation guide for Astro sites and applications.

Research Notes#

  • Astro layouts are the preferred global HTML location for browser scripts.
  • Astro middleware can intercept requests and responses for SSR or on-demand rendering.
  • Fully static Astro output has no request-time middleware; AI Analytics must run at the hosting edge or reverse proxy in that case.

Primary references:

  • https://docs.astro.build/en/guides/client-side-scripts/
  • https://docs.astro.build/en/guides/middleware/

Human Analytics#

Add the Virent browser script to the shared layout that wraps all public pages.

TXT
---// src/layouts/BaseLayout.astro---<html lang="en">  <head>	<script is:inline      defer      data-write-key="vha_pk_..."      src="https://app.virent.app/js/script.js"    ></script>  </head>  <body>    <slot />  </body></html>

Best practices:

  • Use plain external script markup for the hosted Virent script.
  • Do not wrap pageview tracking in a hydrated island.
  • Confirm every public route uses the layout.
  • Use client-side code only for optional custom event tracking.

Verification:

  • Build and preview the Astro site.
  • Inspect the rendered head and Network requests.
  • Refresh Human Analytics status.

Troubleshooting:

  • If the script is absent, confirm all routes use the edited layout.
  • If CSP blocks the script, allow Virent in script-src and connect-src.
  • If custom events do not fire, confirm event code runs in a client-side script or hydrated component.

AI Analytics#

For SSR or on-demand Astro deployments, use src/middleware.ts.

ENV
VIRENT_SITE_ID=site_...VIRENT_INGEST_SECRET=vha_sk_...VIRENT_INGEST_ENDPOINT=https://app.virent.app/v1/ingest/bot
TS
// src/middleware.tsimport type { MiddlewareHandler } from "astro"const staticAssetPattern = /\.(?:png|jpg|jpeg|gif|svg|ico|webp|css|js|map|txt|xml)$/iconst aiCrawlerPattern = /GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|claudebot|Claude-Web|Claude-User|Claude-SearchBot|PerplexityBot|PerplexityBot\/|Perplexity-User|Perplexity-User\/|Google-CloudVertexBot|DeepSeekBot|DeepSeekSpider|CCBot|Applebot|Bytespider|meta-externalagent|meta-webindexer|meta-externalfetcher|Amazonbot|DuckAssistBot|PetalBot|YouBot/iexport const onRequest: MiddlewareHandler = async (context, next) => {  const response = await next()  const userAgent = context.request.headers.get("user-agent") ?? ""  if (!staticAssetPattern.test(context.url.pathname) && aiCrawlerPattern.test(userAgent)) {    await fetch(import.meta.env.VIRENT_INGEST_ENDPOINT, {      method: "POST",      headers: {        "Content-Type": "application/json",        "x-api-key": import.meta.env.VIRENT_INGEST_SECRET,      },      body: JSON.stringify({        siteId: import.meta.env.VIRENT_SITE_ID,        url: context.url.toString(),        host: context.url.host,        path: context.url.pathname,        method: context.request.method,        referer: context.request.headers.get("referer"),        userAgent,        statusCode: response.status,        requestId: crypto.randomUUID(),        timestamp: new Date().toISOString(),      }),    })  }  return response}

Best practices:

  • Use middleware only when the deployment has request-time rendering.
  • Keep secrets in the server runtime, never in client islands.
  • Await next() before sending telemetry so the final status code is available.

Verification:

SH
curl -A "GPTBot" https://your-domain.com/
  • Confirm middleware runs in production.
  • Refresh AI Analytics status.

Troubleshooting:

  • If no crawler events arrive, verify the route is not fully prerendered static output.
  • For static builds, move the same REST call to the hosting edge layer.
  • If status codes are missing, ensure the middleware awaits next().