React Installation Guide
Last researched 2026-08-26
This is the canonical Virent installation guide for React single-page applications, especially Vite-based React apps.
Research Notes#
- Vite treats
index.htmlas source code and as the entry point for React applications. - React SPA code runs in the browser, so it cannot capture AI crawler requests that never execute JavaScript.
- AI Analytics must be installed in the CDN, edge function, reverse proxy, or backend that serves the React build.
Primary references:
- https://vite.dev/guide/
- https://vite.dev/guide/env-and-mode.html
Human Analytics#
Add the Virent browser script to the root index.html file.
HTML
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <script defer data-write-key="vha_pk_..." src="https://app.virent.app/js/script.js" ></script> </head> <body> <div id="root"></div> <script type="module" src="/src/main.tsx"></script> </body></html>Use the browser SDK for custom events.
SH
pnpm add @virent.app/sdkTS
import { initVirent, trackEvent } from "@virent.app/sdk/browser"initVirent({ writeKey: import.meta.env.VITE_VIRENT_WRITE_KEY })await trackEvent({ name: "signup_started", properties: { plan: "pro" },})Best practices:
- Put the script in
index.html, not inside a React component. - Use
VITE_variables only for publishable browser values. - Keep custom tracking helpers in one small module and import them from components that need events.
- Test React Router navigation after installation.
Verification:
- Run a production build and preview it.
- Inspect the rendered HTML for the Virent script.
- Navigate across client routes and confirm pageview requests.
- Refresh Virent installation status.
Troubleshooting:
- If the script is missing, confirm the root
index.htmlwas edited. - If CSP blocks the script, allow the Virent origin in
script-srcandconnect-src. - If local test traffic is needed, temporarily add
data-allow-localhost="true".
AI Analytics#
React itself is not the AI Analytics install point. Install crawler capture in the layer that serves the static React app.
ENV
VIRENT_SITE_ID=site_...VIRENT_INGEST_SECRET=vha_sk_...VIRENT_INGEST_ENDPOINT=https://app.virent.app/v1/ingest/botGeneric edge/server example:
TS
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 async function trackVirentCrawler( request: Request, response: Response, waitUntil?: (promise: Promise<unknown>) => void) { const url = new URL(request.url) const userAgent = request.headers.get("user-agent") ?? "" if (staticAssetPattern.test(url.pathname) || !aiCrawlerPattern.test(userAgent)) { return } const report = fetch(process.env.VIRENT_INGEST_ENDPOINT!, { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": process.env.VIRENT_INGEST_SECRET!, }, body: JSON.stringify({ siteId: process.env.VIRENT_SITE_ID!, url: url.toString(), host: url.host, path: url.pathname, method: request.method, referer: request.headers.get("referer"), userAgent, statusCode: response.status, requestId: crypto.randomUUID(), timestamp: new Date().toISOString(), }), }) if (waitUntil) { waitUntil(report.catch(() => {})) return } await report}Best practices:
- Prefer the provider-native guide in Virent's Connect your site dialog. If your host requires custom code, call this helper after it produces a
Responseand pass itswaitUntilcallback when available. - Do not expose
VIRENT_INGEST_SECRETthroughVITE_variables. - Exclude static assets to avoid noisy crawler events.
Verification:
SH
curl -A "GPTBot" https://your-domain.com/- Confirm the edge/backend layer posts to Virent once for the HTML route.
- Refresh AI Analytics installation status.
Troubleshooting:
- If no crawler events arrive, confirm the request actually reaches the server layer where tracking was installed.
- If the secret appears in built assets, rotate the key and remove it from public env variables.
- If asset events are counted, add extension exclusions.