Skip to main content
Documentation

Supported runtimes and coverage limits

Last reviewed 2026-10-10

One website keeps one websiteId, one publishable browser key and one server secret. Browser and crawler collection are separate channels and are validated independently. The workspace installation status reports per channel: health (receiving, waiting, stale, disconnected, unsupported, unavailable), the last accepted event, when the channel was last validated, and the SDK adapter, version and runtime that last reported on that channel.

The framework guides give copy-paste steps. This page states what each setup can and cannot observe.

Recipes by runtime#

RuntimeInstallObservesDoes not observe
Browser-only or static siteHosted script (/js/script.js) or @virent.app/sdk/browserPageviews, custom events, referrers and campaign attribution, identity links, goalsCrawler requests that do not run JavaScript. Sites without server code need provider logs for crawler coverage.
Next.js on Node.js (proxy.ts)Browser script plus createVirentBotProxy from @virent.app/sdk/next; optional first-party route with createVirentAnalyticsProxyBrowser events and crawler requests that reach the proxyFinal response status (the proxy runs before rendering). Requests answered by a CDN cache never reach the proxy. Still two channels and two keys.
Express or other Node.js SSRBrowser script in the shared layout plus request middleware (the guide's handler, or createVirentBotTracker from @virent.app/sdk/server with a Fetch Request)Browser events and crawler requests handled by that Node.js processRequests served by a CDN or static host in front of the app. The middleware must run at the layer that serves pages.
Cloudflare Workers and other edge isolatesBrowser script plus verified provider logs for crawlersBrowser events; crawler requests as reported by the provider log integrationThe Node.js crawler adapter is not an edge adapter. A crawler report from an edge runtime marks the crawler channel unsupported.

Hosting integrations (Vercel, Cloudflare, AWS CloudFront, Akamai, Netlify, Google Cloud, Fastly, Framer, Webflow) remain available. Their presence is not a certification of every plan or deployment configuration.

Collection controls#

  • Consent. Start consent-managed installs with consent: "pending" (SDK) or data-consent="pending" (hosted script). While pending, nothing is stored or sent. Up to five pageviews requested while pending are held in memory and sent once consent is granted; they are discarded on denial or page unload. Custom events, identity links and goals are never held.
  • Do Not Track. Opt-in. Set respectDoNotTrack: true (SDK) or data-respect-do-not-track="true" (hosted script) to stop collection when the browser sends DNT. Installations that do not set it keep their current behavior.
  • Pause and resume. pause() / window.virent("pause") stop subsequent tracking until resume(); they do not override consent or DNT.
  • Repeated initialization. initVirent with equivalent options reuses the active client and sends no second automatic pageview. Plain values compare by value; functions and objects such as fetch or storage compare by identity. Different options replace the client and log a console warning.
  • First-party forwarding (a /_vr relay or createVirentAnalyticsProxy) relays the same events, so the same controls apply. See "First-party (recommended)" in your framework guide.

Secret boundary#

@virent.app/sdk/server and @virent.app/sdk/next take the server secret. From SDK 0.4.0 their browser export condition resolves to a module that throws, so a client bundle that imports them fails instead of shipping the secret. Client code imports @virent.app/sdk/browser. Keep VIRENT_INGEST_SECRET in server environment variables only.

Adapter reporting#

Browser adapters add sdk: { adapter, version } to the ingest body; server adapters send x-virent-sdk: <adapter>/<version>; runtime=<node|edge|unknown>. Both are optional and ignored by older servers. Ingest logs the adapter and version, and the installation status shows the last report per channel. The report is diagnostic and never changes whether an event is accepted.