WordPress Installation Guide
Last researched 2026-08-26
This is the canonical Virent installation guide for WordPress sites.
Install with your coding agent
Hand the install to Claude Code, Codex, Cursor or another coding agent. It reads this guide, asks for your keys and keeps the server secret out of client code.
Install Virent analytics on my WordPress website. Read the canonical guide first and follow its code exactly: https://stage.virent.app/docs/installation/wordpress.md Install two separate things: 1. Human Analytics (browser): Enqueue the Virent browser script through WordPress front-end hooks. 2. AI Crawler Analytics (server): Create a plugin that sends public crawler page requests to Virent. 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: - Use wp_enqueue_scripts and script_loader_tag from a plugin or child theme instead of editing theme header files directly. - Keep the publishable key in the script tag and the server secret out of browser output. - Prefer a plugin or mu-plugin for portability across theme changes. AI Crawler Analytics best practices: - Install crawler telemetry as a small plugin or mu-plugin rather than editing WordPress core. - Use wp_remote_post with a server-side secret stored in wp-config.php or environment variables. - Skip wp-admin, REST API, cron, login, and static asset requests unless intentionally tracking them. 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: - View source on a public page and confirm the Virent script tag exists. - Open the page in a browser and check Network requests. - Refresh Human Analytics status. - Activate the plugin or mu-plugin. - Request a public page with curl -A "GPTBot". - Refresh AI Analytics status.
Research Notes#
- WordPress front-end scripts should be registered through
wp_enqueue_scripts. - Custom script attributes can be added through
script_loader_tag. - The
shutdownhook runs late enough to read the final WordPress response status. wp_remote_postperforms server-side POST requests.
Primary references:
- https://developer.wordpress.org/reference/functions/wp_enqueue_script/
- https://developer.wordpress.org/reference/hooks/shutdown/
- https://developer.wordpress.org/reference/functions/wp_remote_post/
Human Analytics#
Prefer a small plugin or mu-plugin so tracking survives theme changes.
<?php/** * Plugin Name: Virent Human Analytics */add_action('wp_enqueue_scripts', function () { wp_enqueue_script( 'virent-human-analytics', 'https://app.virent.app/js/script.js', array(), null, false );});add_filter('script_loader_tag', function ($tag, $handle) { if ($handle !== 'virent-human-analytics') { return $tag; } return str_replace( '<script ', '<script defer data-write-key="vha_pk_..." ', $tag );}, 10, 2);Best practices:
- Use
wp_enqueue_scriptsrather than editing WordPress core. - Prefer a plugin, mu-plugin, or child theme over direct theme edits.
- Keep the server secret out of rendered HTML.
- Purge page caches and CDN caches after installation.
Verification:
- Activate the plugin.
- View source on a public page and confirm the Virent script exists.
- Check Network for
/js/script.jsand pageview requests. - Refresh Human Analytics status.
Troubleshooting:
- If the script is absent, confirm the plugin is active and the hook runs on the front end.
- If page caching hides the change, purge cache and CDN.
- If a security plugin blocks the script, allow the Virent origin.
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 for how Virent trusts these headers.
With nginx, add these locations to the site's server block:
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:
<script defer data-api="/_vr" data-write-key="vha_pk_..." src="/_vr/js/script.js"></script>AI Analytics#
Keep server values in wp-config.php or environment-specific configuration.
define('VIRENT_SITE_ID', 'site_...');define('VIRENT_INGEST_SECRET', 'vha_sk_...');define('VIRENT_INGEST_ENDPOINT', 'https://app.virent.app/v1/ingest/bot');Install a plugin or mu-plugin:
<?php/** * Plugin Name: Virent AI Analytics */add_action('shutdown', function () { if (is_admin() || wp_doing_ajax() || wp_doing_cron()) { return; } $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? ''; $path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/'; if ( preg_match('/\.(?:png|jpg|jpeg|gif|svg|ico|webp|css|js|map|txt|xml)$/i', $path) || ! preg_match('/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', $user_agent) ) { return; } wp_remote_post(VIRENT_INGEST_ENDPOINT, array( 'headers' => array( 'Content-Type' => 'application/json', 'x-api-key' => VIRENT_INGEST_SECRET, ), 'body' => wp_json_encode(array( 'siteId' => VIRENT_SITE_ID, 'url' => home_url(add_query_arg(array(), $_SERVER['REQUEST_URI'] ?? '/')), 'host' => $_SERVER['HTTP_HOST'] ?? wp_parse_url(home_url(), PHP_URL_HOST), 'path' => $path, 'method' => $_SERVER['REQUEST_METHOD'] ?? 'GET', 'referer' => $_SERVER['HTTP_REFERER'] ?? null, 'userAgent' => $user_agent, 'statusCode' => http_response_code() ?: 200, 'requestId' => wp_generate_uuid4(), 'timestamp' => gmdate('c'), )), 'timeout' => 2, 'blocking' => false, ));});Best practices:
- Use a plugin or mu-plugin rather than editing core.
- Skip
wp-admin, AJAX, cron, login, REST API, and static asset requests unless intentionally tracking them. - Store
VIRENT_INGEST_SECREToutside rendered HTML. - Confirm the host allows outbound HTTP requests to Virent.
Verification:
curl -A "GPTBot" https://your-domain.com/- Confirm the plugin is active.
- Confirm Virent receives crawler events.
- Refresh AI Analytics status.
Troubleshooting:
- If no events arrive, confirm outbound HTTP is allowed by the host or security plugin.
- If admin requests are tracked, keep admin and login exclusions.
- If the secret appears in page source, move it to server config and rotate it.