Measure the people who visit, including those sent by AI.
Last reviewed 2026-10-19
One browser script collects pageviews, sessions, sources and AI referrals. Add the SDK when you need custom events, identities or goals.
Install#
Add the script once, in the root layout or global template, so it loads on every page. Your framework's installation guide shows where.
<script defer src="https://app.virent.app/js/script.js" data-write-key="vha_pk_..."></script>The publishable key (vha_pk_…) is in Settings → Connection. It is meant for browser code; it only accepts events for your website's allowed origins.
To keep ad blockers from dropping visits, serve the script and events from your own domain. See First-party analytics.
Script options#
| Attribute | Default | Effect |
|---|---|---|
data-write-key | required | The website's publishable key. |
data-allow-localhost | false | Set "true" to collect on localhost while testing. |
data-consent | granted | Start as pending or denied when a consent banner decides first. |
data-respect-do-not-track | false | Set "true" to skip browsers that send Do Not Track. |
data-api | script host | Relay prefix, such as /_vr, for first-party collection. |
Consent and pausing#
The script exposes window.virent for consent banners and other controls. Commands sent before the script loads are queued if you define the queue first:
<script> window.virent = window.virent || function () { (window.virent.q = window.virent.q || []).push(arguments) }</script>virent("consent", "granted") // or "denied" or "pending"virent("pause") // stop collecting until resumevirent("resume")virent("pageview") // send a pageview manuallyvirent("event", { name: "signup_started", properties: { plan: "growth" } })With consent pending, up to five pageviews are held and sent once consent is granted, or discarded on denied.
Single-page apps#
The script follows client-side navigation (history.pushState, replaceState and back/forward) and sends one pageview per new path or query. Test a few route changes after installing.
Custom events, identity and goals#
Install the SDK when the browser script is not enough:
pnpm add @virent.app/sdk@^0.3.0import { identify, initVirent, pageview, trackEvent, trackGoal } from "@virent.app/sdk/browser"initVirent({ writeKey: "vha_pk_..." }) // sends the first pageviewawait trackEvent({ name: "signup_started", properties: { plan: "growth" } })await identify({ userId: "customer_123", traits: { plan: "growth" } })await trackGoal({ name: "signup_completed", idempotencyKey: "order_123" })initVirentsends one pageview. In a single-page app using the SDK alone, callpageview()on each route change.identifyattaches an ID you choose to the visitor. Send your own opaque ID, not an email address or other personal data.idempotencyKeymakes a retried goal count once.resetVirent()discards the active client so you can callinitVirentagain. It does not clear the stored visitor or session ID.
Send pageviews from either the script or the SDK, not both, so each page is counted once.
Goals and funnels#
Add a goal#
In Conversions, choose Add goal and enter the goal name your site sends with trackGoal, such as signup_completed. Add a description if it helps your team.
Add a funnel#
Choose Add funnel, give it a name, then set a starting page, an optional next action (an event name) and an optional completed goal. The funnel shows how many people reach each step.
AI referrals#
Visits are grouped by source: AI, search, social, referral, direct or unknown. A visit counts as an AI referral when it comes from one of these assistants, or carries its name as the UTM source:
| Assistant | Referrer |
|---|---|
| ChatGPT | chatgpt.com, chat.openai.com |
| Claude | claude.ai |
| Perplexity | perplexity.ai |
| Gemini | gemini.google.com |
| Copilot | copilot.microsoft.com |
| Grok | grok.com |
| Poe | poe.com |
| You.com | you.com |
Many AI apps send no referrer, so some AI traffic arrives as direct. AI referrals are a floor, not the total.
Privacy#
- The script sets no cookies; it keeps a visitor and session ID in the site's own browser storage.
- Do not send passwords, payment data, health data, government IDs, precise location or other sensitive personal data in events, traits or URLs.
- Avoid personal data in page paths and query strings; they are collected as part of the page URL.
Troubleshooting#
No pageviews#
Check that /js/script.js loads on the page, the key is the full publishable key, and you are not testing on localhost without data-allow-localhost.
The browser blocks the script#
Allow https://app.virent.app in your Content-Security-Policy script-src and connect-src, or relay it first-party.
Pageviews look doubled#
Check that only the script or only the SDK sends pageviews.
Route changes are missing#
With the SDK alone, call pageview() after each client-side navigation.
Analytics overview
How the Virent Analytics dashboard works - human traffic and AI crawler requests side by side, date ranges, page details, data health and plan limits.
AI Crawler Analytics
Capture AI crawler requests on the server, edge or CDN logs, understand crawler purposes, the AI crawlers Virent recognizes, what is stored, and how to verify.