# Vue Installation Guide

> Install Virent Human Analytics and AI Crawler Analytics on Vue.

Canonical: https://stage.virent.app/docs/installation/vue
Last updated: 2026-08-26

This is the canonical Virent installation guide for Vue single-page applications, especially Vue apps scaffolded with Vite.

### Install with your coding agent

Paste this prompt into Claude Code, Codex, Cursor or another coding agent.

```text
Install Virent analytics on my Vue website.

Read the canonical guide first and follow its code exactly:
https://stage.virent.app/docs/installation/vue.md

Install two separate things:
1. Human Analytics (browser): Install pageview tracking in the Vite document and optionally add a Vue composable for events.
2. AI Crawler Analytics (server): Add crawler capture to the server, edge function, or reverse proxy in front of the Vue app.

Values I will give you (they are in Virent under Settings > Connection):
- Publishable browser key, starts with vha_pk_. Safe in browser code.
- Site ID (VIRENT_SITE_ID) and server secret (VIRENT_INGEST_SECRET, starts with vha_sk_). Server only.
Ask me for them. Never invent a key or use a masked preview such as vha_sk_••••.

Human Analytics best practices:
- Add the script to the root index.html file used by Vite.
- Keep custom event helpers in a small composable or utility imported by components that need tracking.
- Use Vue Router navigation tests to verify route-change pageviews.

AI Crawler Analytics best practices:
- Capture AI crawler requests at the edge, CDN, reverse proxy, or backend that serves the Vue bundle.
- Never expose VIRENT_INGEST_SECRET through VITE_ variables or client-side Vue code.
- Skip static assets and only track document/page requests unless you intentionally need asset-level bot telemetry.

Rules:
- Keep VIRENT_INGEST_SECRET in server environment variables. Never put it in client code, public env variables (NEXT_PUBLIC_, VITE_, PUBLIC_) or committed files.
- Exclude API routes, static assets, images, favicons, robots.txt and sitemaps from crawler capture.
- If the site sends a Content-Security-Policy, allow https://app.virent.app in script-src and connect-src.
- Do not change unrelated code.

When you finish, list the files you changed and how I verify each path:
- Run pnpm build and preview the built app.
- Open DevTools Network and verify /js/script.js loads.
- Refresh Human Analytics status after visiting the site.
- Request a Vue route with a crawler-like user agent.
- Confirm the edge/server layer posts to Virent once for the HTML route.
- Refresh AI Analytics installation status.
```

## Research Notes

- The official Vue SPA setup uses Vite and a root `index.html` entry point.
- Vue client code cannot capture AI crawlers that do not execute browser JavaScript.
- AI Analytics belongs in Nuxt, a backend, CDN worker, edge function, or reverse proxy when using plain Vue.

Primary references:

- https://vuejs.org/guide/quick-start
- https://vite.dev/guide/

## Human Analytics

Add the Virent browser script to `index.html`.

```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="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
```

Optional event helper:

```sh
pnpm add @virent.app/sdk
```

```ts
import { initVirent, trackGoal } from "@virent.app/sdk/browser"

initVirent({ writeKey: import.meta.env.VITE_VIRENT_WRITE_KEY })

export function trackSignupCompleted(orderId: string) {
  return trackGoal({
    name: "signup_completed",
    idempotencyKey: orderId,
  })
}
```

Best practices:

- Keep the pageview script in `index.html`.
- Put event helpers in a composable or utility module.
- Use only publishable keys in `VITE_` variables.
- Test Vue Router navigation after install.

Verification:

- Build and preview the Vue app.
- Inspect the document head for the Virent script.
- Confirm pageview requests appear after route navigation.
- Refresh Human Analytics status.

Troubleshooting:

- If the script is absent, verify the correct `index.html` was edited.
- If CSP blocks the script, allow the Virent origin.
- If route changes are missed, confirm the Virent script loaded before testing navigation.

### First-party (recommended)

Ad blockers and privacy tools often block third-party analytics hosts, which silently drops visits. Relay the script and events through your own domain under `/_vr`, and load the script with `data-api="/_vr"` so events go to your domain too. The relay must forward the visitor's IP and country in `x-virent-forwarded-for` and `x-virent-forwarded-country`, with your website's secret key (`vha_sk_…`) in `x-virent-proxy-key`; without the key Virent ignores the forwarded headers and sees your server's network instead of your visitors'. Relay only `/_vr/js/script.js` and `/_vr/v1/*`, and never forward cookies or authorization headers. See [First-party analytics](/docs/installation/first-party) for how Virent trusts these headers.

With nginx, add these locations to the site's server block:

```text
location = /_vr/js/script.js {
  proxy_pass https://app.virent.app/js/script.js;
  proxy_set_header Host app.virent.app;
  proxy_ssl_server_name on;
  proxy_set_header Cookie "";
}

location /_vr/v1/ {
  proxy_pass https://app.virent.app/v1/;
  proxy_set_header Host app.virent.app;
  proxy_ssl_server_name on;
  proxy_set_header Cookie "";
  proxy_set_header Authorization "";
  proxy_set_header X-Virent-Forwarded-For $remote_addr;
  # Your website's secret key: Virent trusts the forwarded IP only with it.
  proxy_set_header X-Virent-Proxy-Key "vha_sk_...";
}
```

On Cloudflare, deploy a Worker on the `example.com/_vr/*` route that copies only `accept-language`, `content-type`, `origin` and `user-agent`, sets `x-virent-forwarded-for` from `cf-connecting-ip`, `x-virent-forwarded-country` from `request.cf.country` and `x-virent-proxy-key` from a Worker secret holding your website's secret key, and fetches the same path without `/_vr` from `https://app.virent.app`. The dashboard install panel has the full Worker.

Then load the script from your domain:

```html
<script
  defer
  data-api="/_vr"
  data-write-key="vha_pk_..."
  src="/_vr/js/script.js"
></script>
```

## AI Analytics

Install AI Analytics outside the Vue browser bundle, in the host or backend layer.

```env
VIRENT_SITE_ID=site_...
VIRENT_INGEST_SECRET=vha_sk_...
VIRENT_INGEST_ENDPOINT=https://app.virent.app/v1/ingest/bot
```

Use the same edge/server pattern as React:

```ts
const staticAssetPattern = /\.(?:png|jpg|jpeg|gif|svg|ico|webp|css|js|map|txt|xml)$/i
const 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|Bytespider|meta-externalagent|meta-webindexer|meta-externalfetcher|Amazonbot|DuckAssistBot|YouBot/i

export 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:

- Use Nuxt if you want framework-native server middleware.
- Keep `VIRENT_INGEST_SECRET` out of Vue code.
- Skip static files and only capture document/page requests by default.

Verification:

```sh
curl -A "GPTBot" https://your-domain.com/
```

- Confirm the edge/backend layer runs for the route.
- Refresh AI Analytics status.

Troubleshooting:

- If the app is static-only, install tracking in the host platform instead of Vue components.
- If the secret leaks into the bundle, rotate it and remove all public references.
- If events include built assets, add file extension exclusions.
