# Virent - full content > Connect human analytics, AI crawler activity, LLM visibility, prompts, citations and conversions in one evidence-led platform. Virent is an AI discovery analytics platform: it monitors what AI engines answer about a brand and which pages they cite, records AI crawler requests to the brand's site, and counts the visits and conversions AI answers send, with sampled answers and crawl logs as evidence. This file holds every public page as Markdown; https://virent.app/llms.txt is the short index, and each page is also available alone at its own URL with `.md` appended. Generated: 2026-11-04 --- # Get your brand cited by AI > Connect human analytics, AI crawler activity, LLM visibility, prompts, citations and conversions in one evidence-led platform. Canonical: https://virent.app/ Last updated: 2026-07-29 See what ChatGPT says about your brand, and the visits it sends you. Monitors answers on the leading AI platforms: ChatGPT, Google AI Overviews, Google AI Mode, Perplexity, Gemini, Claude, Grok, DeepSeek and Meta AI. Your buyers ask AI before they search. ChatGPT, Claude, Gemini and Perplexity already answer questions about your market. Most brands have no idea what those answers say about them. ## Three signals, one picture Most tools show one side. Virent joins the answers that cite you, the AI crawlers that read your pages and the people AI sends. - **AI answers**: Know when AI recommends you, and when it picks a competitor. [Explore LLM Visibility](https://virent.app/visibility) - **AI crawlers**: Know which pages AI crawlers read, and which they skip. [Explore AI Crawler Analytics](https://virent.app/bots) - **AI visitors**: Know how many people AI sends to your site, and what they do. [Explore Analytics](https://virent.app/analytics) ## Up and running in three steps Connect once, then check in when you want to know what changed. 1. **Add your brand**: Add your website and the brands you compete with. Your first AI answers arrive while you finish setting up. 2. **We monitor it for you**: We ask the questions your buyers ask every day on all 9 AI engines, and keep every answer and cited source. 3. **See what to fix**: Pages AI reads but never cites, prompts where a competitor wins, and the visits AI sends you. ## The full loop, in one platform - **Data collection**: AI crawler visits, AI answers and the visits AI sends, every day. - **Analysis**: Mentions, citations, share of voice and coverage. - **Diagnosis**: Pages AI reads but never cites, prompts a competitor wins. - **Action**: Prioritized fixes and articles you approve. ## Before you sign up ### Do I need a developer? Not for answers and citations: add your site and your prompts and Virent starts asking the AI. The tracking script and crawler logs take about five minutes. You can send the setup instructions to your developer from inside the app. ### How soon do I see data? Your first prompt run happens during setup. Visitors and crawlers start counting as soon as the script and log connection are live. ### Which AI engines do you track? ChatGPT, Google AI Overviews, Google AI Mode, Perplexity, Gemini, Claude, Grok, DeepSeek and Meta AI. Every plan includes all of them, with your prompts checked daily. ### Is my data safe? Visitors get pseudonymous IDs, tracking respects consent, and secrets are encrypted. The security page has the details. ## Related - [Pricing](https://virent.app/pricing): Compare Virent plans for LLM visibility, prompt monitoring, AI crawler analytics, human analytics and reporting. - [Documentation](https://virent.app/docs): Install Virent human analytics and AI crawler tracking, configure visibility monitoring and verify each data path. - [llms.txt](https://virent.app/llms.txt): An index of Virent for language models, with when to use it. - [OpenAPI specification](https://virent.app/openapi.json): The documented public HTTP API. - [Contact](https://virent.app/contact): Talk to the team behind Virent. --- # See how people and AI crawlers use your site. > Measure human traffic and AI crawler activity together, with observed answer citations alongside and clear coverage limits for each signal. Canonical: https://virent.app/analytics Last updated: 2026-07-29 Analytics for human traffic and AI crawler activity, with observed answer citations alongside. Coverage depends on what you install. ## Visits, crawler requests, and answer evidence in one place. - **Which pages bring visitors in, and what do those visits lead to?** Answered in Analytics / Pages: Entry pages with the sessions they start and the goals those sessions reach. - **Which AI crawlers request the site, which pages do they reach, and what status do they receive?** Answered in Analytics / Crawlers: Crawler requests by family, route and response status. - **Which pages are cited in monitored answers, and are those pages also crawled and visited?** Answered in Analytics / Pages: Answer citations, crawler requests and visits for each page, side by side and never added together. - **Where does the available evidence stop?** Answered in Analytics / Coverage: Each signal shows whether its collection path is in place, so a gap reads as missing data, not as zero. ## What Analytics measures ### Human traffic Pageviews, visitors, sessions, landing pages, referrers, campaigns, events, goals, and funnels from the browser script or SDK. Sessions are derived from observed events. ### AI crawler activity Crawler requests captured at the server, edge, middleware, or log layer, classified by crawler family, with the requested URL and response status. A classification is not proof of identity. ### Observed answer citations Pages cited in answers to your monitored Visibility prompts appear beside traffic and crawler activity. They are sampled API observations for your prompt and provider scope, not a count of every AI conversation. ### Pages Open a page to see its human activity, crawler coverage, and answer references side by side. Each stays a separate measure, never one blended score. ### Referral and campaign context Referrer and UTM context is preserved where the browser provides it, so AI-referred visits can be measured directly. ## Coverage depends on what you install. Each signal comes from a different collection path, so a site can have one without the others. A missing path means the data is unavailable, not that activity was zero. - Human traffic needs the browser script or SDK on the pages you want to measure. - Crawler activity needs a server, edge, middleware, or log integration, because most crawlers do not run browser JavaScript. - Answer citations need Visibility monitoring and reflect the prompts, providers, and schedule you configure. - Requests, citations, and visits are related signals. Virent does not add them together or treat one as proof of another. - [Explore AI Crawler Analytics](https://virent.app/bots) - [Explore LLM Visibility](https://virent.app/visibility) ## Know what the website evidence can and cannot prove. Follow a visit from the answer that mentioned you to the goal it reached, and keep unobservable influence labeled. > Someone can meet your brand in an AI answer and arrive days later through another channel. Unless the path is observable, Virent keeps that relationship inferred or unknown. ## Add collection when the question needs it. Install the browser script for pageviews, or the npm SDK for explicit events and goals. Add server or edge capture when you need crawler requests. Never place the Virent server ingest secret in browser code. Localhost traffic is skipped by default. - [Choose a framework in Documentation](https://virent.app/docs#installation) ## Workflow 1. **Establish the measurement plan**: Choose the pages, events, goals, and crawler routes that answer a real business question. Avoid collecting fields simply because they are available. 2. **Verify each data path**: Confirm a pageview is sent, the expected goal arrives, and a crawler request reaches the workspace from the server layer. 3. **Compare useful segments**: Review landing pages, channels, crawler families, and observable AI referrers with sample size and time range visible. 4. **Connect the evidence**: Compare visitor outcomes with crawler and citation changes without treating correlation as causation. ## For teams ### Growth and marketing Evaluate acquisition paths and goals with direct referrals kept separate from inferred influence. ### SEO Check crawler access and response status for the pages that matter, beside their visits and citations. [Explore AI Crawler Analytics](https://virent.app/bots) ### Content See whether cited or high-visibility pages also support meaningful on-site behavior. [Explore Content Agent](https://virent.app/content-agent) ## Frequently asked questions ### Does Virent replace our existing web analytics? Virent is built around AI discovery investigations. It measures core website activity, but the reason to use it is the connected view across human behavior, crawler activity, prompts, and citations. Whether it replaces another tool depends on your reporting requirements. ### Can Virent attribute every AI-influenced visit? No. A visit is attributed directly when the referral or campaign path is observable. Other relationships stay labeled as inferred or unknown. ### Do answer citations show real AI search volume? No. Citations come from API answers to the prompts you monitor, sampled on your schedule. They show what those answers referenced, not how often people ask AI products about a topic. ### Do we need to install anything for visibility monitoring? No. URL-only visibility monitoring needs no site instrumentation. Add the browser script or server capture when the question includes on-site behavior or crawler access. ### What should we avoid sending? Do not send passwords, payment-card data, health data, government identifiers, precise location, secrets, or other sensitive personal information unless Virent has expressly agreed in writing to process it. ## Related - [AI Crawler Analytics](https://virent.app/bots) - [LLM Visibility](https://virent.app/visibility) - [Privacy Policy](https://virent.app/privacy) --- # See how AI crawlers actually request your site. > Classify AI crawler requests, measure site coverage, inspect response status and validate robots, middleware and routing changes. Canonical: https://virent.app/bots Last updated: 2026-07-29 Classify crawler requests at the server, then find the pages machines reach, miss, or revisit. ## Move from server-log noise to a useful map of machine access. - **Which crawler families request the site, and which routes do they reach?** Answered in Analytics / Crawlers: Requests grouped by crawler family, with the routes each one reaches. - **Which high-value pages have little or no observed crawl activity?** Answered in Analytics / Crawlers: Routes ranked by crawler requests in the period, so the ones with little or none stand out. - **Where do crawlers receive redirects, blocks, or server errors?** Answered in Analytics / Crawlers: Response statuses crawlers received, so redirects, blocks and errors stand out by route. - **What changed after a robots, middleware, or routing update?** Answered in Analytics / Crawlers: Crawler requests to the same routes before and after the date of a change. ## Crawler activity happens without running your browser analytics. Most crawlers request HTML without executing browser JavaScript, so Virent captures requests in the server, edge, middleware, reverse proxy, or plugin hook instead. Server secrets stay in server-side environment variables. - [Choose a framework in Documentation](https://virent.app/docs#installation) ## Core measurements ### Crawler classification Group requests using maintained user-agent and crawler-family rules, with the reported agent preserved for inspection. A classification is not proof of cryptographic identity. ### Request volume and timing Review counts and trends by family, route, section, method, and time range. A spike is a prompt to inspect, not automatically harmful. ### Coverage Compare the pages crawlers requested with the inventory that matters. Coverage describes observed requests, not guaranteed indexing or model use. ### Response status See the status returned to crawlers and find repeated redirects, blocked routes, missing pages, or server failures. ### Rules and change context Compare behavior around robots, middleware, proxy, or routing changes to validate the observed effect rather than the intent. ## Being accessible, being selected, and being cited are different states. A request proves that a machine reached an observed layer. It does not prove that a provider indexed the page or cited it in an answer. Virent makes the gap measurable: 1. inspect crawler coverage and response behavior for the pages that matter; 2. compare them with citation URLs from repeatable prompt runs; 3. separate access problems from relevance and source-selection questions; 4. repeat the comparison after a change. - [Explore LLM Visibility](https://virent.app/visibility) - [Explore Content Agent](https://virent.app/content-agent) ## Workflow 1. **Install at the request layer**: Use the recommended hook for your framework. Exclude API routes, static assets, favicons, robots files, and sitemaps unless the measurement plan needs them. 2. **Verify with a controlled request**: Send a request with a known crawler user agent and confirm the event appears. This tests the integration, not the external crawler's network identity. 3. **Establish coverage**: Group routes into business-relevant sections and compare observed requests with the expected page inventory. 4. **Investigate changes**: Use status, route, timing, and citation evidence to decide whether the next step is technical, editorial, or simply more observation. ## For teams ### SEO teams Connect crawl behavior to visibility and citations without reducing it to a single score. [Explore LLM Visibility](https://virent.app/visibility) ### Developers and platform teams Inspect concrete routes and responses, keep secrets server-side, and validate changes with controlled requests. ### Content teams Find pages that receive crawler attention but never appear as sources in monitored answers. ## Frequently asked questions ### Why not use the browser script for crawler analytics? Many crawlers do not run the browser script. Capture has to happen before browser JavaScript, at the server or another request-interception layer. ### Does Virent verify that every request came from the named company? Virent classifies observed signals such as user agents using its maintained taxonomy, and surfaces stronger verification separately where it is available. A classification alone is not cryptographic identity proof. ### Does a successful crawl mean the page can appear in an AI answer? No. Access is one prerequisite. Indexing, retrieval, source selection, and answer generation are controlled by external providers. ### Can Virent change our robots rules? No. Virent measures and supports decisions. It does not push robots, canonical, middleware, or content changes to your site. --- # Know where your brand appears, and what the answer cites. > Track brand mentions, observable position, citations and competitive share of voice across repeatable prompts and selected AI providers. Canonical: https://virent.app/visibility Last updated: 2026-07-29 Track mentions, citations, and share of voice across the prompts and AI providers you choose to monitor. ## Make brand presence comparable over time. - **How often does the brand appear in the monitored answer set?** Answered in Visibility / Mentions: The share of monitored answers that mention the brand, for a defined set of prompts, providers and period. - **Which URLs and domains are cited, and which competitors appear beside you?** Answered in Visibility / Citations: Citations from monitored answers, with the brands that appear in the same answers. - **How does share of voice vary by provider, topic, region, or language?** Answered in Visibility / Share of voice: Share of voice split by the segments you monitor. - **Does Google's AI Overview cite you, or do you only rank below it?** Answered in Visibility / AI Overview vs organic: For each tracked prompt in Google: whether the AI Overview cites you, and where you rank in the organic results of the same search. - **Which of your pages do AI answers cite, and do AI crawlers still read them?** Answered in Visibility / Cited pages: Your own pages, with how often monitored answers cite them, when AI crawlers last fetched them and the visits AI assistants sent. - **Did visibility move after a content or technical change?** Answered in Visibility / Trends: Visibility for the same scope before and after a dated change. Movement is an association, not proof of cause. ## Open any score to the answer behind it. Share of voice is a way in. The prompt, answer, mentions, and citations stay attached. ## Measurement model ### Topics and prompt groups Monitor durable market questions rather than a loose list of prompts. A topic is an intent cluster; prompts are the repeatable measurements inside it. ### Providers and models Select the providers relevant to your audience. Results always carry their provider and model context, because answer behavior differs across systems. ### Mentions and observable position Position is used only when the answer provides a meaningful ordering. Virent does not manufacture ranking from unordered prose. ### Citations and sources Cited URLs and domains are preserved with the answer, showing gained, lost, and recurring sources between comparable runs. ### Competitive share of voice Compare the confirmed brand and competitor set inside the selected scope. Share of voice is not market share. ## Workflow 1. **Define a stable scope**: Confirm the brand, competitors, topics, prompt groups, providers, regions, and languages that matter to the decision. 2. **Establish a baseline**: Run the same prompt set and review the evidence before treating the first score as a benchmark. 3. **Monitor meaningful changes**: Watch mention, position, citation, and competitor movement. Compare compatible runs rather than mixing scopes. 4. **Diagnose the gap**: Use crawler activity, page evidence, and competitor sources to form a specific hypothesis. 5. **Validate after the work**: Run the same measurement again and compare the answer and source evidence. ## Connected product evidence ### Prompt Monitoring Supplies the repeatable run history that makes a visibility trend explainable. [Explore Prompt Monitoring](https://virent.app/prompts) ### AI Crawler Analytics Separates pages machines rarely request from pages requested but never selected as sources. [Explore AI Crawler Analytics](https://virent.app/bots) ### Analytics Shows observable referral sessions and goals, without turning every visibility change into an attributed outcome. [Explore Analytics](https://virent.app/analytics) ## For teams - [Content Agent](https://virent.app/content-agent): Use source and answer changes to prioritize editorial investigation. - [AI Crawler Analytics](https://virent.app/bots): Compare machine access, visibility, and citation evidence. - [Analytics](https://virent.app/analytics): Monitor brand presence and the outcomes you can observe. ## Frequently asked questions ### Is the Virent visibility score universal? No. It summarizes the configured prompt, provider, model, competitor, region, language, and time scope, and the interface keeps that scope visible. ### Does a mention count as a citation? No. A mention is brand presence in an answer. A citation is a source reference attached to that answer. Virent measures them separately. ### Can Virent guarantee that a provider will keep citing a page? No. External providers control crawling, indexing, retrieval, source selection, and answer generation. Virent measures observed results and changes. ### Do we need to install code? No. Visibility monitoring can begin with a website and a defined scope. Add browser or server telemetry when you need on-site outcomes or crawler evidence. --- # Track the questions shaping your market. > Organize repeatable prompt groups, preserve AI answers and citations, and compare brand, competitor and source changes over time. Canonical: https://virent.app/prompts Last updated: 2026-07-29 Run the same prompts across selected AI providers and keep the answers, citations, and changes that follow. ## Turn changing answers into a reviewable history. - **Which questions matter to each topic, audience, or stage of discovery?** Answered in Visibility / Prompts: The prompt library, grouped by the topics you define, with each prompt's result by provider. - **How do answers vary by provider or model?** Answered in Visibility / Runs: One prompt's answers side by side, by provider. - **Which prompts are worth tracking, and how much are they asked?** Answered in Visibility / Prompt suggestions: Suggested prompts come from real searches, People Also Ask questions and questions AI answers already cover, each with an estimated demand score. - **What do ChatGPT, Gemini and Google AI Mode actually show people?** Answered in Visibility / Answers: ChatGPT and Gemini as people see them in the apps, plus Google AI Mode, with the products and shopping cards they show. - **When does the brand appear, and which competitors appear beside it?** Answered in Visibility / Answers: Each preserved answer, with the brand and competitor mentions found in it. - **Which changes are material enough for a team to review?** Answered in Visibility / Runs: Run-to-run differences: mentions, competitors and citations gained or lost. ## See exactly what changed between comparable runs. Each run keeps its prompt, scope, answer, and sources, so a comparison can show what moved without hiding the text underneath. ## Build a durable prompt library ### Group by decision Organize prompts by topic, audience, journey stage, product, or region. A group should help the team interpret results, not just store them. ### Keep ownership clear Assign an owner and document why each prompt matters. Remove prompts that no longer support a decision. ### Preserve scope Provider, model, region, language, brand, and competitor context travel with the prompt. Comparisons only mean something when the scope is compatible. ### Schedule repeatable runs Use a cadence the team can actually review. More runs do not automatically create more insight. ## Review changes that meet a defined condition. Alerting belongs inside the monitoring workflow, and every alert links to the run and evidence behind it. A team may choose to review: - a brand mention gained or lost; - a competitor moving into or out of an observable position; - a citation URL or domain gained or lost; - repeated run failures or missing provider coverage. ## Workflow 1. **Define the question set**: Choose prompts that represent a durable market or customer question. Document the topic and owner. 2. **Confirm comparison scope**: Select the providers, models, regions, languages, brand, and competitors the decision requires. 3. **Establish the baseline**: Run the set, review the evidence, and resolve prompts that are ambiguous or unstable. 4. **Monitor and investigate**: Review answer, mention, citation, and competitor changes. Read the underlying run before assigning a cause. 5. **Validate**: Repeat the same measurement after the team acts. ## Connected product evidence - [LLM Visibility](https://virent.app/visibility): Summarizes patterns across the prompt library. - [AI Crawler Analytics](https://virent.app/bots): Shows whether relevant pages receive observed crawler requests. - [Analytics](https://virent.app/analytics): Shows directly observable visits and outcomes. ## For teams ### Content teams Turn answer and source changes into a specific editorial hypothesis, then validate it after publishing. [Explore Content Agent](https://virent.app/content-agent) ### SEO teams Compare prompt evidence with crawler access, status, and page coverage. [Explore AI Crawler Analytics](https://virent.app/bots) ### Marketing teams Monitor brand and competitor presence across category questions, with referral outcomes kept separate. [Explore Analytics](https://virent.app/analytics) ## Frequently asked questions ### Why monitor prompts instead of checking an AI tool manually? Manual checks are useful for exploration but hard to compare. Prompt Monitoring preserves the question, scope, answer, sources, and run history that repeatable review needs. ### Will the same prompt always return the same answer? No. Provider behavior varies with model changes, retrieval, timing, and region. Monitoring makes that variability visible; it does not remove it. ### Are all run-to-run changes meaningful? No. Decide which changes matter to your decision and read the underlying evidence before acting. ### Is Prompt Monitoring the same as LLM Visibility? Prompt Monitoring owns the question set and run evidence. LLM Visibility summarizes brand, competitor, citation, and source patterns across it. ## Related - [Documentation](https://virent.app/docs) --- # Turn observed content gaps into reviewed articles. > Turn observed content gaps into researched, human-reviewed articles, published through GitHub after approval and funded by a separate capped allowance. Canonical: https://virent.app/content-agent Last updated: 2026-07-29 Content Agent researches and drafts from the gaps Virent observes. Your team reviews and approves every article before Virent publishes it through GitHub. Content Agent is in early access for selected workspaces. ## From an observed gap to an approved article. Every step keeps its evidence attached, and a person decides what moves forward. ## Briefs built from what AI engines read ### Questions AI engines research Each brief lists the searches ChatGPT runs for the topic and the questions Google shows, and marks which ones the outline already covers. ### Pages AI Overviews cite See the competitor pages Google's AI Overviews cite for the topic, and choose which ones Content Agent reads as references. ### In your market Research runs in the brand's market and language, so a Brazilian brief is researched in Portuguese, in Brazil. ## What stays under your control ### Human approval Nothing is published without an explicit approval of the exact revision. Changing an approved draft needs a new approval. ### Publishing through GitHub Install the Virent GitHub App on the repositories you choose. Publishing opens a pull request by default. Deployment and live checks are separate, visible steps. ### No silent changes Content Agent never changes your site on its own and never reverses a publication automatically. Reverting is a separate action a person approves. ### Claims and sources Factual claims are checked against attached sources during review. Each decision is recorded against the revision it applies to. ### A separate, capped allowance Research and drafting use a Content allowance with a hard cap, separate from Analytics and Visibility limits. There are no automatic overages. ## For teams ### Content Move from answer and citation evidence to a reviewed draft without giving up editorial judgment. ### Measurement Compare each article's page with its crawler requests, visits, and citations before and after publication. [Explore Analytics](https://virent.app/analytics) ## Frequently asked questions ### Does Content Agent publish automatically? No. A person must approve the exact revision before Virent opens a pull request or commits to your repository. Content Agent does not publish on a schedule or on its own. ### Which publishing destinations are supported? GitHub repositories connected through the Virent GitHub App, plus Markdown and HTML export. Other content-management systems are not supported. ### Which services process content data? Research uses Firecrawl to search and fetch public pages, and DataForSEO for search demand and results-page data. Drafting uses AI models through Vercel AI Gateway. The Privacy Policy and Data Processing Addendum list these providers. ### How is Content Agent usage counted? Content Agent work uses its own capped allowance. Scheduled Visibility monitoring stays within your Visibility plan limits and is not charged twice. ### Who can use Content Agent? Content Agent is in early access for selected workspaces. Contact Virent to ask about access. ## Related - [Privacy Policy](https://virent.app/privacy) - [Data Processing Addendum](https://virent.app/dpa) - [Documentation](https://virent.app/docs) --- # Pricing > Compare Virent plans for LLM visibility, prompt monitoring, AI crawler analytics, human analytics and reporting. Canonical: https://virent.app/pricing Last updated: 2026-07-29 Every plan includes all 9 AI engines and every product. Plans differ by how much you monitor. Prices in USD; annual billing charges 10 of 12 months (2 months free). ## Plans | Plan | Monthly | Annual (a month, billed yearly) | For | | --- | --- | --- | --- | | Business Core | $99 | $83, $990 a year | One brand with all core products. | | Business Growth (recommended) | $249 | $208, $2,490 a year | More brands, prompts, and daily monitoring. | | Business Scale | $599 | $499, $5,990 a year | Multiple workspaces and advanced monitoring capacity. | | Business Plus | $999 | $833, $9,990 a year | Internal multi-brand teams with higher volume. | ### Business Core - 25 tracked prompts, run daily - 1 brand - 2 seats - 150 AI credits a month - 50K AI crawler visits a month ### Business Growth - 60 tracked prompts, run daily - 2 brands · extra brands $49 a month - 5 seats - 500 AI credits a month - 250K AI crawler visits a month ### Business Scale - 150 tracked prompts, run daily - 5 brands · extra brands $49 a month - 10 seats - 1,200 AI credits a month - 1M AI crawler visits a month ### Business Plus - 250 tracked prompts, run daily - 10 brands · extra brands $49 a month - 25 seats - 2,000 AI credits a month - 5M AI crawler visits a month ## Every plan includes - LLM Visibility - Prompt Monitoring - AI Crawler Analytics - Human Analytics - Content Agent - Reports - AI engines: ChatGPT, Google AI Overviews, Google AI Mode, Perplexity, Gemini, Claude, Grok, DeepSeek and Meta AI ## Compare plans The same product on every plan; these are the limits that change. ### Monitoring | Limit | Business Core | Business Growth | Business Scale | Business Plus | | --- | --- | --- | --- | --- | | Tracked prompts (Asked every day on each AI engine, shared across your brands) | 25 | 60 | 150 | 250 | | Brands (A website, or a brand without one) | 1 | 2 | 5 | 10 | | Extra brands (Each adds one brand, not prompts) | — | $49 a month each | $49 a month each | $49 a month each | | AI engines (All engines on every plan) | 9 | 9 | 9 | 9 | | Competitors per brand | 3 | 8 | 15 | 15 | | Markets per brand (A country and its language, such as Brazil · Portuguese) | 1 | 1 | 3 | 3 | ### Analytics | Limit | Business Core | Business Growth | Business Scale | Business Plus | | --- | --- | --- | --- | --- | | AI crawler visits (A month · going over never drops data) | 50K | 250K | 1M | 5M | | Human events (A month · going over never drops data) | 100K | 500K | 2M | 10M | ### Content Agent | Limit | Business Core | Business Growth | Business Scale | Business Plus | | --- | --- | --- | --- | --- | | AI credits (A month · a standard article uses 40) | 150 · ~3 articles | 500 · ~12 articles | 1,200 · ~30 articles | 2,000 · ~50 articles | ### Team | Limit | Business Core | Business Growth | Business Scale | Business Plus | | --- | --- | --- | --- | --- | | Seats | 2 | 5 | 10 | 25 | | Workspaces | 1 | 1 | 3 | 5 | ### API and exports | Limit | Business Core | Business Growth | Business Scale | Business Plus | | --- | --- | --- | --- | --- | | Reports and CSV export | Included | Included | Included | Included | | API keys | Included | Included | Included | Included | | Read API | — | Included | Included | Included | | Webhooks | — | — | Included | Included | | Write API | — | — | Included | Included | ## Frequently asked questions ### Are all product surfaces included? Every plan includes Human Analytics, AI crawler analytics, daily prompt monitoring on every AI engine, Content Agent, reports, API keys, and CSV exports. Capacity and some advanced capabilities vary by plan. ### Is there a free trial or a free plan? No. You choose a plan and pay first. Setup starts right after: your business profile, competitors, suggested prompts, and the first run. ### How does annual billing work? Annual billing charges 10 months for 12, so you get 2 months free. Checkout shows the total, billing terms, renewal, and taxes before you pay. ### What counts as a brand? A brand is one website you monitor, including its subdomains, or a company, creator, or local business tracked by name without a website. Core includes 1 brand, Growth 2, Scale 5, and Plus 10. Tracked prompts are shared across your brands. Competitors are counted per brand and never use a brand. ### Can we add more brands? On Growth and above, extra brands are $49 a month each, added from billing settings. An extra brand adds no prompts. On Core, upgrade to Growth for a second brand. ### What happens when usage approaches a limit? Usage and limits stay visible in the product. Analytics never stops collecting. If you go over your human events or AI crawler visits, we keep your data and ask you to upgrade after two months over. Tracked prompts and AI credits stop at the plan limit. Nothing is charged automatically: you can upgrade or buy an opt-in credit top-up. ### Can we monitor any website? You may monitor only domains, properties, data, and accounts you own or are authorized to analyze. ### Do you offer agency plans? Agency plans exist for teams managing authorized client workspaces. Contact Virent for details. ### Where can we ask a pricing or procurement question? Contact Virent with the number of brands, prompts, regions, languages, and users you need. Do not send passwords, API keys, or sensitive customer data. ## Related - [Plans, Limits and Billing](https://virent.app/docs/workspace/plans-and-billing): Plan limits, billing, plan changes and over-limit behavior. - [Terms of Service](https://virent.app/terms) - [Privacy Policy](https://virent.app/privacy) - [Help Center](https://virent.app/help) - [Contact](https://virent.app/contact) --- # Find the shortest path to a useful answer. > Find Virent setup, verification, data, billing, privacy and troubleshooting guidance or contact support. Canonical: https://virent.app/help Last updated: 2026-07-29 Pick the task: start monitoring, install analytics, verify data, manage the account, or contact Virent. ## Start here ### Set up a website Add a domain you are authorized to monitor, confirm the business profile, and define the prompt groups that matter. [Read the getting-started documentation](https://virent.app/docs) ### Install Human Analytics Install the site-wide browser script with your publishable write key, then verify a pageview. [Choose a framework](https://virent.app/docs#installation) ### Install AI Crawler Analytics Capture requests at the server or edge, keep the ingest secret in a protected environment variable, and verify a controlled request. [Choose a framework](https://virent.app/docs#installation) ### Configure visibility and prompts Confirm topics, prompts, providers, competitors, and regions, then review the baseline evidence before relying on a score. - [LLM Visibility](https://virent.app/visibility) - [Prompt Monitoring](https://virent.app/prompts) ## Troubleshooting ### Human events are not arriving Confirm the browser script loads on the affected route, the publishable key is correct, Content Security Policy permits the script and request, localhost behavior is intentional, and the test is not blocked by a browser extension. ### Crawler events are not arriving Confirm the capture hook runs before browser JavaScript, covers the intended route, uses the full server secret rather than a masked preview, and does not exclude the test path. ### Static files create crawler events Exclude framework internals, API routes, image optimization, favicons, robots files, sitemaps, and common static file extensions. ### A visibility result is empty Distinguish a completed run with no observed brand presence from a queued, running, failed, or incomplete run. Confirm the prompt and provider scope. ### A citation or answer changed Open the affected runs and compare the full answers, source URLs, provider, model, time, region, and language. One change may reflect normal provider variability. ## Data and privacy ### What does Virent collect? Collection depends on what the customer enables: visibility monitoring processes configured prompts, provider responses, mentions, citations, competitors, and run context; Human Analytics processes enabled pageviews, sessions, referrers, campaign context, custom events, and goals; AI Crawler Analytics processes request and response metadata used for classification and coverage. ### What should we avoid sending? Do not send passwords, payment-card data, health data, government identifiers, precise location, secrets, or other sensitive personal information unless Virent has expressly agreed in writing to process it. - [Read the Privacy Policy](https://virent.app/privacy) ## Where can legal or privacy teams review terms? - [Privacy Policy](https://virent.app/privacy) - [Terms of Service](https://virent.app/terms) - [Data Processing Addendum](https://virent.app/dpa) - [Security](https://virent.app/security) ## Account and billing ### Choosing a plan Estimate monitored brands, prompts, providers, competitors, telemetry volume, workspaces, and seats. ### Access and password help Use the sign-in and password-reset flows. Virent support will not ask for a password or server secret. ### Workspace access Contact the workspace owner or administrator for role and membership changes. Include the workspace name, but do not send private exports unless support specifically requests them through an approved channel. - [View Pricing](https://virent.app/pricing) ## Include context, not credentials. For a useful first response, provide: > Do not email passwords, API keys, server secrets, raw sensitive data, or unredacted customer exports. - the affected workspace or website; - the product area; - the approximate time and time zone; - the route, prompt, or operation involved; - the expected and observed behavior; - a request or event identifier when safely available; - whether the issue is reproducible. - [Contact support](https://virent.app/contact) ## Frequently asked questions ### Can we use Virent before installing code? Yes. URL-only LLM visibility monitoring can begin without site instrumentation. ### Does successful setup guarantee crawler traffic or citations? No. Setup verifies Virent's data path. External providers control their own crawling, retrieval, source selection, and answers. --- # Make AI discovery measurable. > Learn why Virent connects human analytics, AI crawler activity, LLM visibility, prompts, citations and outcomes. Canonical: https://virent.app/about Last updated: 2026-07-29 A telemetry-first platform that connects human analytics, AI crawler activity, LLM visibility, prompts, and citations. ## AI discovery fragmented the website analytics story. Web analytics starts when a person arrives. Server logs show machines but not the answer environment. Visibility scores hide the prompts beneath them. Teams are left with separate questions: > Virent brings those observations into one investigation without pretending they are interchangeable. - **Did an AI crawler reach the page?** Answered in Analytics / Crawlers: Crawler requests captured on the server, by route and response status. - **Did the brand appear in the answer?** Answered in Visibility / Answers: Preserved answers, with the brand's mention and position where it appears. - **Which source did the answer cite?** Answered in Visibility / Citations: The sources each monitored answer cited, the brand's own among them. - **Did a measurable visit follow?** Answered in Analytics / AI referrals: A visit with a detectable AI referrer, and the goal it reached. - **What changed after the team acted?** Answered in Visibility / Runs: Run-to-run differences after a dated change, kept as an association. ## Telemetry first. Claims second. A summary metric should lead back to the evidence that produced it: - request-level crawler activity; - repeatable prompt and provider scope; - preserved answers and citations; - pageviews, sessions, events, and goals; - before-and-after comparisons; - explicit labels for direct, inferred, and unknown. ## Start simple. Add fidelity when the question changes. Begin with URL-only visibility monitoring. Add Human Analytics for on-site behavior and goals, and AI Crawler Analytics for server-side request evidence. No one needs every data path enabled to get a useful first measurement. ## Who Virent is for ### Growth teams Connect measurable acquisition to the broader AI discovery environment. ### Content teams Turn answer, citation, and page evidence into focused editorial hypotheses. ### SEO teams Separate crawler access issues from visibility and source-selection questions. ### Digital marketing teams Measure brand and competitor presence with attributed outcomes kept distinct from inferred influence. ## Human approval, not autonomous website control. Virent measures, connects, and helps teams prioritize. Content Agent can draft articles from observed gaps, but nothing is published to your site without a person approving it, and Virent never makes silent changes. It cannot guarantee that a provider will crawl, mention, cite, or refer to a brand. You own the decision and the change. ## Operating principles ### Keep evidence attached Preserve prompts, answers, sources, requests, pages, events, and time context behind the summary. ### Name uncertainty Distinguish direct observation, responsible inference, and unknowns. ### Collect with purpose Enable the minimum instrumentation required by the measurement plan. ### Explain in plain language Make the product accessible to non-technical teams without hiding important technical boundaries. ### Validate after action Use the same evidence set before and after a change. --- # Tell us what you are trying to measure or resolve. > Contact Virent about product access, pricing, support, integrations, privacy, legal or security matters. Canonical: https://virent.app/contact Last updated: 2026-07-29 Early access, pricing, support, integrations, privacy, legal terms, or a suspected security issue. ## Choose a contact path ### Product access and pricing Include: - company and website; - number of brands (websites, or brands tracked without one); - approximate prompt, provider, and language scope; - whether you need Human or AI Crawler Analytics; - target timing. *Email subject: Virent product inquiry* ### Product support Include: - affected workspace or website; - product area, and approximate time with time zone; - route, prompt, or operation; - expected and observed behavior; - a safe request or event identifier when available. *Email subject: Virent support request* ### Developer and integration questions Include: - framework and version; - hosting or request layer; - the signal you want to capture; - sanitized error text; - the framework guide you already tried. *Never send the full ingest secret.* ### Privacy and legal Say whether the request concerns the Privacy Policy, Terms, the Data Processing Addendum, data-subject rights, or subprocessors. Identify the account or email involved, without sending identity documents. *Email subject: Virent privacy or legal request* ### Security reports Describe the affected surface, observed behavior, reproduction steps, and potential impact. Do not access data that is not yours or include secrets in the first message. *Email subject: Private security report* ## Contact details This address currently handles product, support, privacy, legal, and security inquiries. - [virent.app@gmail.com](mailto:virent.app@gmail.com) ## Before contacting support - [Documentation](https://virent.app/docs) - [Help Center](https://virent.app/help) - [Pricing](https://virent.app/pricing) - [Security](https://virent.app/security) - [Privacy Policy](https://virent.app/privacy) - [Terms of Service](https://virent.app/terms) - [Data Processing Addendum](https://virent.app/dpa) ## Final note Virent uses what you send to review and answer the request, in line with the Privacy Policy. Never send passwords, API keys, server secrets, payment data, or personal information the request does not need. --- # Protect the evidence without hiding the boundaries. > Review Virent's data minimization, access control, encryption, secret handling, logging and security-reporting practices. Canonical: https://virent.app/security Last updated: 2026-07-29 Purposeful collection, protected credentials, workspace separation, secure transport, and documented incident response. ## Security at a glance ### Collect what you enable Each product collects only what it needs; secrets and sensitive personal information should never be sent. ### Roles and separate workspaces Role-based access and separate customer workspaces. You assign roles and remove access that is no longer needed. ### Browser keys and server secrets Publishable keys for the browser; server ingest secrets stay in protected server, edge or backend environments. ### Scoped GitHub publishing Short-lived tokens for one repository, approval checked again before writing, and never a force push. ### Hardened responses Response headers such as HTTP Strict Transport Security and nosniff are one layer of defense. ### Logged and monitored Logging, monitoring and a documented incident response, with a path to report a security issue. ## Data minimization Instrumentation is progressive, so you enable only what you need: > Collection choices and lawful notices remain a shared responsibility between Virent and the customer. - URL-only visibility monitoring needs no browser or server telemetry; - Human Analytics collects the events you enable for your measurement plan; - AI Crawler Analytics captures the request metadata used for classification and coverage; - secrets and sensitive personal information should never be sent. ## Access and workspace controls Virent uses role-based access, authentication protections, protected production credentials, and separation of customer workspaces. You are responsible for: - protecting account credentials; - assigning appropriate workspace roles; - removing access that is no longer required; - securing their own systems and integrations; - notifying Virent of suspected unauthorized access. ## Encryption and secrets Data in transit uses current industry-standard transport protocols, with encryption at rest where the storage layer supports it. Publishable browser keys and server secrets serve different purposes: - publishable keys may be used by the approved browser integration; - server ingest secrets belong only in protected server, edge, proxy, or backend environments; - no secret should be committed to source, bundled into the browser, or emailed to support. ## Content Agent and GitHub publishing Content Agent publishes only revisions a person has approved, and only to GitHub repositories you connect through the Virent GitHub App. - you choose which repositories the app can access, and can revoke that access in GitHub at any time; - each publishing step uses a short-lived GitHub token limited to one repository and the permissions that step needs; - Virent checks the approval, your current permissions, and the destination again immediately before writing; - publishing never force-pushes, and Virent never reverses a remote publication automatically; - fetched web pages and repository text are treated as evidence, never as instructions to the agent. ## Application and platform protections Application controls include response headers such as: > Headers are one layer of defense, not a complete security program, and their details evolve with the architecture. - HTTP Strict Transport Security; - X-Content-Type-Options: nosniff; - frame restrictions; - strict referrer policy; - permissions restrictions for camera, geolocation, and microphone. ## Logging, monitoring, and response Virent maintains logging, monitoring, dependency management, backup and recovery, and documented incident response proportionate to the service and its risk. If Virent becomes aware of a Security Incident affecting Customer Personal Data, it notifies the customer without undue delay, as described in the Data Processing Addendum. ## Vendors and subprocessors Vendors and subprocessors that provide infrastructure and product capabilities are subject to review and contractual data-protection obligations. The Data Processing Addendum lists the current subprocessors, including the web research, search data, storage, model, and GitHub providers Content Agent uses, and the data each receives. - [Read the Data Processing Addendum](https://virent.app/dpa) ## Secure implementation guidance ### Human Analytics - Use the publishable write key in browser code. - Limit collection to the measurement plan. - Review consent and notice requirements. - Configure Content Security Policy deliberately. ### AI Crawler Analytics - Store the full ingest secret in a protected environment variable. - Capture only intended routes. - Exclude APIs, static assets, robots files, and sensitive paths. - Treat robots directives as guidance, not access control. ### API and integrations - Use documented interfaces. - Scope and rotate keys. - Do not build against internal application endpoints. - Sanitize logs and support artifacts. - [Read the documentation](https://virent.app/docs) ## Reporting a security issue Report suspected security issues privately to virent.app@gmail.com with the subject "Private security report". There is no public bug-bounty or safe-harbor program. ### Include - the affected surface; - a concise description; - safe reproduction steps; - observed and potential impact; - a contact method for follow-up. ### Do not - access data that is not yours; - disrupt or degrade the service; - use social engineering; - send live credentials or unnecessary personal information; - disclose publicly before Virent can investigate. ## Frequently asked questions ### Is Virent certified under a specific security framework? No certification is claimed on this page. Contact Virent for the security information currently available. ### Does Virent use customer data to train general-purpose AI models? Virent's current Privacy Policy states that it does not use Customer Data to train general-purpose AI models unless the customer expressly agrees. ### Is robots.txt enough to protect private content? No. Private content requires authentication and server-side authorization. ### How long does Virent keep data? Default periods are 395 days for human analytics events, 90 days for crawler analytics events, 730 days for usage records, 90 days for raw web pages fetched for content research, and 30 days for operational logs. Approved article revisions stay with the article until it is deleted. The Privacy Policy describes these defaults and the limits of deletion from backups and remote destinations. ### Where are privacy roles and international-transfer terms described? Review the Privacy Policy and Data Processing Addendum. --- # Start with the signal you need to measure. > Install Virent human analytics and AI crawler tracking, configure visibility monitoring and verify each data path. Canonical: https://virent.app/docs Last updated: 2026-07-29 Start with visibility, then add browser or crawler capture only for the signal you need. - [Read the quickstart](/docs/get-started/quickstart) - [Choose your framework](#installation) ## Start here ### From sign-up to your first answers The eight onboarding steps, connecting Analytics, and how to verify each data path. [Quickstart](/docs/get-started/quickstart) ### What each number means Brands, prompts, sampled answers, mentions, citations, crawler requests and attribution, and the limits of each. [How Virent measures](/docs/get-started/concepts) ### Hand the docs to your agent Markdown for every page, llms.txt, and ready-made prompts for Claude Code, Codex, Cursor and others. [Use with AI agents](/docs/get-started/ai-agents) ### Something isn't working Fixes for missing data, changing answers, keys, limits and billing. [Troubleshooting and FAQ](/docs/reference/troubleshooting) ## Choose an instrumentation mode ### URL-only visibility monitoring Use it for: prompts, answers, mentions, observable position, citations, competitors, and share of voice. Site change required: No. [Start here: Visibility](/docs/visibility/overview) ### Human Analytics Use it for: pageviews, sessions, referrers, campaigns, custom events, goals, and funnels. Site change required: A site-wide browser script or SDK installation. [Read next: Human Analytics](/docs/analytics/human-analytics) ### AI Crawler Analytics Use it for: crawler classification, request volume, routes, response status, coverage, and crawl rules. Site change required: A server-side, edge or log integration. [Read next: AI Crawler Analytics](/docs/analytics/ai-crawlers) ### Content Agent Use it for: turning observed gaps into researched, reviewed articles published through GitHub after human approval. Site change required: GitHub access to your site's repository. [Early access: Content Agent](/docs/content-agent/overview) ## Choose your framework Each framework guide covers Human Analytics and AI Crawler Analytics where the framework supports them, and starts with a prompt for your coding agent. ## JavaScript and TypeScript - [Next.js](/docs/installation/nextjs) - [React](/docs/installation/react) - [Vue](/docs/installation/vue) - [Nuxt](/docs/installation/nuxt) - [Astro](/docs/installation/astro) - [SvelteKit](/docs/installation/sveltekit) - [Express](/docs/installation/express) ## Server and CMS - [Laravel](/docs/installation/laravel) - [WordPress](/docs/installation/wordpress) ## Hosting integrations No server code, or pages served from a CDN cache? Capture AI crawlers from your host's logs or an edge Worker instead. See [Hosting integrations](/docs/integrations/overview). - [Vercel](/docs/integrations/vercel) - [Cloudflare](/docs/integrations/cloudflare) - [AWS CloudFront](/docs/integrations/aws-cloudfront) - [Akamai](/docs/integrations/akamai) - [Netlify](/docs/integrations/netlify) - [Google Cloud](/docs/integrations/google-cloud) - [Fastly](/docs/integrations/fastly) - [Framer](/docs/integrations/framer) - [Webflow](/docs/integrations/webflow) ## Framework not listed? Use the platform pattern that matches your architecture: - a global site template for the browser script; - a server, edge, reverse-proxy, middleware, or plugin hook for crawler requests, or your host's logs (see [AI Crawler Analytics](/docs/analytics/ai-crawlers)); - environment variables for server secrets; - route exclusions for APIs, static assets, images, robots files, and sitemaps. Contact support before inventing a public SDK API or payload. ## Keys and data boundaries ### Publishable write key Use the publishable key (`vha_pk_…`) in browser tracking. It identifies the site's public ingest configuration and only accepts events from the website's allowed origins. ### Server ingest secret Use the server secret (`vha_sk_…`) only in server, edge, proxy, middleware, or protected backend code. Never hard-code it in committed source or expose it to the browser. See [Keys and secrets](/docs/workspace/keys). ### Ingest endpoint Use Virent's default endpoint unless the implementation requires an approved custom or proxied endpoint, such as a [first-party relay](/docs/installation/first-party). ### Sensitive data Do not send passwords, payment-card data, health data, government identifiers, precise location, API secrets, or other sensitive personal information unless Virent has expressly agreed in writing to process it. ## Product guides - [Analytics](/docs/analytics/overview) - [Visibility](/docs/visibility/overview) - [Prompts and answers](/docs/visibility/prompts) - [Brands and competitors](/docs/visibility/brands-and-competitors) - [Actions](/docs/actions) - [Content Agent](/docs/content-agent/overview) - [Team and roles](/docs/workspace/team-and-roles) - [Plans and billing](/docs/workspace/plans-and-billing) - [API and SDK Reference](/docs/api) ## More resources - [Help Center](/help) - [Security](/security) - [Privacy Policy](/privacy) - [Data Processing Addendum](/dpa) ## Need help choosing the right integration? Describe your framework, hosting layer, and the signals you need to measure. Do not send passwords, API keys, server secrets, or sensitive customer data. - [Contact Virent](/contact) --- # Build against documented Virent interfaces. > Virent SDKs, keys and the OpenAPI specification for browser analytics ingest, AI crawler ingest and the analytics read API. Canonical: https://virent.app/docs/api Last updated: 2026-07-29 Browser analytics, server crawler ingest and the analytics read API, with an OpenAPI specification for every supported HTTP operation. - [Read installation guides](/docs#installation) - [Contact developer support](/contact) ## Supported integration paths ### Browser script Use the site-wide browser script when the implementation needs standard pageview and session collection with minimal custom code. The script uses the site's publishable write key. It must not receive the server ingest secret. ### Browser SDK Use @virent.app/sdk/browser when the implementation needs explicit initialization, pageviews, custom events, customer-chosen identity data, or goals. Use examples from the tested framework guides. Do not infer exports from old homepage snippets. ### Framework and server integrations Use the documented framework helper or request-layer pattern to capture AI crawler requests. Keep the full ingest secret in a server environment variable. ### HTTP interfaces Virent's supported HTTP operations are described in the [OpenAPI specification](/openapi.json): payloads, authentication, idempotency, size limits, errors and rate limits. A route that is not in the specification is internal. ### Authorized data access Plans that include the read API can read analytics with a private API key. The read operations in the OpenAPI specification are the supported surface; do not assume that an internal application endpoint is a supported customer API. ## @virent.app/sdk The current release is `0.3.1`. Install it with `pnpm add @virent.app/sdk@^0.3.0`. | Entry point | Runs in | Exports | | --- | --- | --- | | `@virent.app/sdk/browser` | Browser | `initVirent`, `pageview`, `trackEvent`, `identify`, `trackGoal`, `resetVirent`, `createVirentBrowserClient` | | `@virent.app/sdk/server` | Server | `createVirentBotTracker`, `classifyBotUserAgent` | | `@virent.app/sdk/next` | Next.js server files | `createVirentBotProxy` (crawler capture in `proxy.ts`), `withVirentBotProxy` (wraps an existing proxy), `createVirentAnalyticsProxy` (first-party route handler) | Usage: [Human Analytics](/docs/analytics/human-analytics), [AI Crawler Analytics](/docs/analytics/ai-crawlers), [First-party analytics](/docs/installation/first-party) and the [framework guides](/docs#installation). ## Browser script `https://app.virent.app/js/script.js` takes these attributes: `data-write-key` (required), `data-allow-localhost`, `data-consent`, `data-respect-do-not-track`, `data-api` (relay path or origin) and `data-api-url` (full ingest URL, which wins over `data-api`). It exposes `window.virent` with the commands `consent`, `pause`, `resume`, `pageview` and `event`. See [Human Analytics](/docs/analytics/human-analytics#script-options). ## Authentication model ### Publishable keys Publishable keys identify permitted browser ingest configuration. They may appear in client code but should still be limited to the intended site and origin policy. ### Server secrets Server ingest secrets authenticate protected server-to-server writes. Store them in environment variables or the hosting platform's secret store. Never include them in browser bundles, public repositories, screenshots, support messages, or documentation examples. ### API keys Private API keys (`vnt_sk_`) read one workspace's data through the read API on plans that include it. Owners, admins and developers create, list and revoke them in Settings → Connection; the full key is shown once. A key works only in the workspace it was created in, expires a year after it is created, and stops working when the member who created it leaves the workspace or loses API access. Send it in the `x-api-key` header. ## OpenAPI specification [`https://virent.app/openapi.json`](/openapi.json) describes the Virent API in OpenAPI 3.1. Every operation has an `operationId`, a description, typed parameters and response schemas, so API clients and AI agents can import it directly. | Operation | Endpoint | Authentication | | --- | --- | --- | | `ingestBrowserEvents` | `POST /v1/ingest/batch` | Publishable key (`vha_pk_`), from an allowed origin | | `ingestCrawlerRequest` | `POST /v1/ingest/bot` | Server secret (`vha_sk_`) | | `getAnalyticsOverview` | `GET /v1/analytics/overview` | Private API key (`vnt_sk_`) | | `getAnalyticsTimeseries` | `GET /v1/analytics/timeseries` | Private API key (`vnt_sk_`) | | `getAnalyticsTraffic` | `GET /v1/analytics/traffic` | Private API key (`vnt_sk_`) | | `getAnalyticsPages` | `GET /v1/analytics/pages` | Private API key (`vnt_sk_`) | | `getAnalyticsReferrers` | `GET /v1/analytics/referrers` | Private API key (`vnt_sk_`) | | `getAnalyticsVisitors` | `GET /v1/analytics/visitors` | Private API key (`vnt_sk_`) | Read operations answer 402 when the workspace's plan does not include the read API. Rate limits and error bodies are in each operation's responses. To call these operations from a terminal or an AI agent without writing code, use the [Virent CLI](/docs/cli). ## Rate limits Ingest is limited per key and visitor network: 120 requests a minute for browser ingest and 240 for crawler ingest, plus a per-website events-per-minute ceiling that scales with the plan. Every ingest response reports the request bucket in the IETF `RateLimit-Policy` and `RateLimit` fields, alongside `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`: ```http RateLimit-Policy: "browser";q=120;w=60 RateLimit: "browser";r=119;t=55 ``` The read API allows 300 requests a minute per client IP, counted before the key is checked. Every read response, including 401s, reports it the same way: ```http RateLimit-Policy: "read";q=300;w=60 RateLimit: "read";r=299;t=55 ``` `q` is the quota, `w` the window in seconds, `r` the requests left and `t` the seconds until the window resets. A throttled request answers 429 with `Retry-After` in seconds; wait at least that long before retrying. ## Versioning and deprecation - The major version is in the path: every operation is under `/v1`. - Backward-compatible changes ship within `/v1` without notice: new operations, new optional parameters and new response fields. Ignore fields you do not recognize. - Breaking changes ship only under a new major version, such as `/v2`. The previous version keeps working until its sunset date. - A deprecated operation is marked `deprecated: true` in the OpenAPI specification and announced on this page. Its responses carry a `Deprecation` header ([RFC 9745](https://www.rfc-editor.org/rfc/rfc9745)) with the date it was deprecated and a `Sunset` header ([RFC 8594](https://www.rfc-editor.org/rfc/rfc8594)) with the date it stops working. - Virent gives at least 6 months between deprecation and sunset. No operation is deprecated today. ## Current developer guidance For an implementation today: 1. choose the relevant framework guide; 2. use the exact browser or server pattern documented there; 3. create the correct key in the workspace; 4. store server secrets outside committed source; 5. verify the event path; 6. contact Virent before building against an endpoint that is not in the OpenAPI specification. ## Frequently asked questions ### Can we use internal /api/* routes as a public API? No. Internal application routes are not a supported public contract unless they are explicitly documented here. ### Is every /v1/* route public? No. Only the operations in the OpenAPI specification are supported. A versioned path alone does not define support, authorization, or customer availability. ### Where should we get code samples? Use the public framework installation guides and the released package documentation. Samples must be tested against the current package version. ### How do we request an integration that is not documented? Contact Virent with the framework, hosting layer, data direction, expected volume, and intended use. Do not send credentials or customer data. ## Use a supported path before building a custom one. Start with the framework guides. If your architecture needs an interface the OpenAPI specification does not cover, contact Virent first. - [Read installation guides](/docs#installation) - [Contact developer support](/contact) --- # Read Virent analytics and check installs from a terminal. > Install the Virent command line (@virent.app/cli) to read analytics with an API key and validate a publishable key against your site from a terminal or an AI agent. Canonical: https://virent.app/docs/cli Last updated: 2026-10-27 The Virent CLI wraps the public API for scripts, CI jobs and AI coding agents. Every command prints JSON. ## Install ```bash npx @virent.app/cli --help ``` Or install it globally for the `virent` command: ```bash npm install --global @virent.app/cli ``` It needs Node.js 20 or later and has no dependencies. ## Read analytics Reading analytics needs a private API key (`vnt_sk_`) from **Settings → Connection** on a plan that includes the read API. See [Keys and secrets](/docs/workspace/keys). ```bash export VIRENT_API_KEY=vnt_sk_… virent analytics overview --website virent analytics pages --website --from 2026-10-01 --to 2026-10-27 virent analytics timeseries --website --interval hour --from 2026-10-26 ``` | Report | What it returns | | --- | --- | | `overview` | Human analytics totals: pageviews, events, sessions, bounces and visitors | | `timeseries` | Pageviews and sessions per hour or day | | `traffic` | Totals, time series and goal conversions in one call | | `pages` | Pageviews per page path | | `referrers` | Sessions per referrer and traffic source, including AI referrers | | `visitors` | Visitors by browser, device, operating system and country | The range defaults to the last 7 days. `--timezone` takes an IANA time zone and defaults to `UTC`. Each report is one operation in the [OpenAPI specification](/openapi.json). ## Check an install Validate a publishable key (`vha_pk_`) against a page on your site: ```bash virent install check --key vha_pk_… --url https://www.example.com/ ``` The CLI sends one pageview to browser ingest with `dryRun=1` from that page's origin. Virent checks the key, the allowed origin and host, the plan and the rate limits, and stores nothing. A `validated` event means the browser script with that key will be accepted on that site. ## Other commands | Command | What it does | | --- | --- | | `virent openapi` | Prints the OpenAPI 3.1 description of the public API | | `virent --version` | Prints the CLI version | | `virent --help` | Lists commands and options | Errors go to stderr with exit code 1. They include the API's error message and, when rate limited, the `Retry-After` seconds. `--base-url` (or `VIRENT_API_URL`) points the CLI at another Virent origin. ## Use with AI agents Coding agents can run the CLI directly. Give the agent the key through `VIRENT_API_KEY` in its environment, never in a chat message, and ask it to run `virent --help` first. --- # Next.js Installation Guide > Install Virent Human Analytics and AI Crawler Analytics on Next.js. Canonical: https://virent.app/docs/installation/nextjs Last updated: 2026-08-26 This is the canonical Virent installation guide for Next.js projects. It covers Human Analytics browser tracking and AI Analytics server-side crawler tracking. Coverage limits: `proxy.ts` runs on Node.js before rendering, so the final response status is unknown, and requests answered from a CDN cache never reach it. Import `@virent.app/sdk/next` only from server files; from SDK 0.4.0 a client bundle that imports it fails to load. Edge isolates need provider logs for crawler coverage. See [Supported runtimes and coverage limits](/docs/installation/runtimes-and-coverage). ### Install with your coding agent Paste this prompt into Claude Code, Codex, Cursor or another coding agent. ```text Install Virent analytics on my Next.js website. Read the canonical guide first and follow its code exactly: https://virent.app/docs/installation/nextjs.md Install two separate things: 1. Human Analytics (browser): Add the Virent browser script through next/script in the root App Router layout. 2. AI Crawler Analytics (server): Install the SDK helper, set server-only environment values, and add a root proxy.ts file. 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: - Install the browser script once in app/layout.tsx so it loads across all App Router routes. - Use next/script instead of a raw script tag when working inside a Next.js layout. - Keep the publishable key in the data-write-key attribute; it is safe for the browser, unlike the crawler secret. AI Crawler Analytics best practices: - Use proxy.ts for Next.js 16+ projects and keep the matcher narrow enough to exclude API routes, static assets, images, robots.txt, sitemaps, and common files. - Store the crawler secret in server environment variables only. Never expose it through NEXT_PUBLIC_ variables or client bundles. - Capture crawler requests before rendering so bots that never execute JavaScript are still measured. 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: - Open a production or preview page and check Network for /js/script.js. - Confirm a pageview request is sent after navigation. - Refresh Virent installation status and confirm Human Analytics changes to receiving events. - Run the app and request a page with curl -A "GPTBot". - Refresh Virent installation status and confirm AI Analytics changes to receiving crawler events. - Inspect server logs for failed outbound requests to the Virent ingest endpoint. ``` ## Research Notes - Next.js 16 App Router supports global third-party scripts through `next/script` in layouts. - Next.js 16 renamed the `middleware.ts` file convention to `proxy.ts`. New AI Analytics installs should use `proxy.ts`. - Proxy runs before routes render and should use a matcher that excludes static assets and framework internals. Primary references: - https://nextjs.org/docs/app/guides/scripts - https://nextjs.org/docs/app/api-reference/file-conventions/proxy ## Human Analytics Install Human Analytics in `app/layout.tsx` so the browser script loads on every App Router route. ```tsx import Script from "next/script" export default function RootLayout({ children }) { return ( {children}
``` Use the browser SDK for custom events. ```sh pnpm add @virent.app/sdk ``` ```ts 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.html` was edited. - If CSP blocks the script, allow the Virent origin in `script-src` and `connect-src`. - If local test traffic is needed, temporarily add `data-allow-localhost="true"`. ### 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 ``` ## 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/bot ``` Generic edge/server example: ```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) => 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 `Response` and pass its `waitUntil` callback when available. - Do not expose `VIRENT_INGEST_SECRET` through `VITE_` 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. --- # Vue Installation Guide > Install Virent Human Analytics and AI Crawler Analytics on Vue. Canonical: https://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://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
``` 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 ``` ## 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) => 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. --- # Nuxt Installation Guide > Install Virent Human Analytics and AI Crawler Analytics on Nuxt. Canonical: https://virent.app/docs/installation/nuxt Last updated: 2026-08-26 This is the canonical Virent installation guide for Nuxt applications. ### Install with your coding agent Paste this prompt into Claude Code, Codex, Cursor or another coding agent. ```text Install Virent analytics on my Nuxt website. Read the canonical guide first and follow its code exactly: https://virent.app/docs/installation/nuxt.md Install two separate things: 1. Human Analytics (browser): Add the Virent browser script through useHead in the root Nuxt app component. 2. AI Crawler Analytics (server): Set server env values and add a Nitro server plugin for completed crawler requests. 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 useHead in app/app.vue for one global script install. - Set defer on the script so the Nuxt app is not blocked. - Keep custom event SDK usage in client-only composables or plugins. AI Crawler Analytics best practices: - Use a Nitro server plugin and its afterResponse hook so crawler telemetry includes the final response status. - Use runtime config or platform environment variables for the secret; never expose it through public runtime config. - Filter out static assets and API routes unless those routes should be measured. 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: - Open a Nuxt page and inspect the head for the Virent script. - Navigate to another route and confirm pageview traffic. - Refresh Human Analytics installation status. - Start Nuxt in a server-capable mode. - Request a route with curl -A "GPTBot". - Refresh AI Analytics status in Virent. ``` ## Research Notes - Nuxt `useHead` manages scripts in the document head. - Nitro server plugins can subscribe to `afterResponse`, after the final status is known. - Static-only output has no request-time Nitro hook; install crawler tracking at the hosting provider instead. Primary references: - https://nuxt.com/docs/4.x/api/composables/use-head - https://nuxt.com/docs/4.x/directory-structure/server ## Human Analytics Add the browser script globally in `app/app.vue`. ```vue ``` Best practices: - Keep the script global in `app/app.vue`. - Use `defer` so Nuxt hydration is not blocked. - Keep custom event code in client-side composables or plugins. - Use public runtime config only for publishable values. Verification: - Open a Nuxt route and inspect the head. - Navigate to another route and confirm pageview traffic. - Refresh Human Analytics status. Troubleshooting: - If the script is absent, confirm the project uses `app/app.vue` and the `useHead` call is not conditional. - If CSP blocks Virent, allow the origin in `script-src` and `connect-src`. - If local events are expected, temporarily add `data-allow-localhost="true"`. ### 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 ``` ## AI Analytics Add private env values: ```env VIRENT_SITE_ID=site_... VIRENT_INGEST_SECRET=vha_sk_... VIRENT_INGEST_ENDPOINT=https://app.virent.app/v1/ingest/bot ``` Create a Nitro server plugin: ```ts // server/plugins/virent-crawler.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 default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook("afterResponse", async (event) => { const requestUrl = getRequestURL(event) const userAgent = getHeader(event, "user-agent") ?? "" if (staticAssetPattern.test(requestUrl.pathname) || !aiCrawlerPattern.test(userAgent)) { return } await $fetch(process.env.VIRENT_INGEST_ENDPOINT!, { method: "POST", headers: { "x-api-key": process.env.VIRENT_INGEST_SECRET! }, body: { siteId: process.env.VIRENT_SITE_ID!, url: requestUrl.toString(), host: requestUrl.host, path: requestUrl.pathname, method: event.method, referer: getHeader(event, "referer") ?? null, userAgent, statusCode: event.node.res.statusCode, requestId: crypto.randomUUID(), timestamp: new Date().toISOString(), }, }) }) }) ``` Best practices: - Use the Nitro `afterResponse` hook so telemetry has the final response status and does not delay route handling. - Use private runtime config or server environment variables for the secret. - Move tracking to the CDN/edge layer for static-only Nuxt output. Verification: ```sh curl -A "GPTBot" https://your-domain.com/ ``` - Confirm the Nitro server plugin runs. - Refresh AI Analytics status. Troubleshooting: - If `afterResponse` does not run, confirm the deployment uses a server/Nitro runtime. - If the secret is undefined, check private runtime config and deployment env names. - If events are duplicated, ensure only one middleware or edge layer sends events. --- # Astro Installation Guide > Install Virent Human Analytics and AI Crawler Analytics on Astro. Canonical: https://virent.app/docs/installation/astro Last updated: 2026-08-26 This is the canonical Virent installation guide for Astro sites and applications. ### Install with your coding agent Paste this prompt into Claude Code, Codex, Cursor or another coding agent. ```text Install Virent analytics on my Astro website. Read the canonical guide first and follow its code exactly: https://virent.app/docs/installation/astro.md Install two separate things: 1. Human Analytics (browser): Place the Virent script in the base Astro layout that wraps every page. 2. AI Crawler Analytics (server): Add src/middleware.ts in SSR/on-demand Astro deployments or install the same REST call at the edge for static hosting. 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 browser script once in the shared Astro layout head. - Use plain external script markup for the hosted Virent script; do not bundle it into an island. - Keep event SDK code in client-side components only when custom events are needed. AI Crawler Analytics best practices: - Use Astro middleware only when the deployment has SSR or on-demand rendering. - Keep the crawler secret in the server runtime and never ship it to client islands. - Call next() so Astro can continue rendering the requested page. 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: - Build and preview the Astro site. - Inspect the page head and Network requests. - Refresh Human Analytics status. - Deploy with an SSR-capable adapter or edge layer. - Request a page with curl -A "GPTBot". - Refresh AI Analytics status. ``` ## Research Notes - Astro layouts are the preferred global HTML location for browser scripts. - Astro middleware can intercept requests and responses for SSR or on-demand rendering. - Fully static Astro output has no request-time middleware; AI Analytics must run at the hosting edge or reverse proxy in that case. Primary references: - https://docs.astro.build/en/guides/client-side-scripts/ - https://docs.astro.build/en/guides/middleware/ ## Human Analytics Add the Virent browser script to the shared layout that wraps all public pages. ```astro --- // src/layouts/BaseLayout.astro --- ``` Best practices: - Use plain external script markup for the hosted Virent script. - Do not wrap pageview tracking in a hydrated island. - Confirm every public route uses the layout. - Use client-side code only for optional custom event tracking. Verification: - Build and preview the Astro site. - Inspect the rendered head and Network requests. - Refresh Human Analytics status. Troubleshooting: - If the script is absent, confirm all routes use the edited layout. - If CSP blocks the script, allow Virent in `script-src` and `connect-src`. - If custom events do not fire, confirm event code runs in a client-side script or hydrated component. ### 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 ``` ## AI Analytics For SSR or on-demand Astro deployments, use `src/middleware.ts`. ```env VIRENT_SITE_ID=site_... VIRENT_INGEST_SECRET=vha_sk_... VIRENT_INGEST_ENDPOINT=https://app.virent.app/v1/ingest/bot ``` ```ts // src/middleware.ts import type { MiddlewareHandler } from "astro" 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 const onRequest: MiddlewareHandler = async (context, next) => { const response = await next() const userAgent = context.request.headers.get("user-agent") ?? "" if (!staticAssetPattern.test(context.url.pathname) && aiCrawlerPattern.test(userAgent)) { await fetch(import.meta.env.VIRENT_INGEST_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": import.meta.env.VIRENT_INGEST_SECRET, }, body: JSON.stringify({ siteId: import.meta.env.VIRENT_SITE_ID, url: context.url.toString(), host: context.url.host, path: context.url.pathname, method: context.request.method, referer: context.request.headers.get("referer"), userAgent, statusCode: response.status, requestId: crypto.randomUUID(), timestamp: new Date().toISOString(), }), }) } return response } ``` Best practices: - Use middleware only when the deployment has request-time rendering. - Keep secrets in the server runtime, never in client islands. - Await `next()` before sending telemetry so the final status code is available. Verification: ```sh curl -A "GPTBot" https://your-domain.com/ ``` - Confirm middleware runs in production. - Refresh AI Analytics status. Troubleshooting: - If no crawler events arrive, verify the route is not fully prerendered static output. - For static builds, move the same REST call to the hosting edge layer. - If status codes are missing, ensure the middleware awaits `next()`. --- # SvelteKit Installation Guide > Install Virent Human Analytics and AI Crawler Analytics on SvelteKit. Canonical: https://virent.app/docs/installation/sveltekit Last updated: 2026-08-26 This is the canonical Virent installation guide for SvelteKit applications. ### Install with your coding agent Paste this prompt into Claude Code, Codex, Cursor or another coding agent. ```text Install Virent analytics on my SvelteKit website. Read the canonical guide first and follow its code exactly: https://virent.app/docs/installation/sveltekit.md Install two separate things: 1. Human Analytics (browser): Install the browser script in SvelteKit's app.html template. 2. AI Crawler Analytics (server): Add crawler tracking to the SvelteKit server handle hook. 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 src/app.html so it is present for every rendered document. - Keep the tag in the head near %sveltekit.head% and keep the publishable key unchanged. - Use the npm SDK from client modules for custom events only. AI Crawler Analytics best practices: - Use src/hooks.server.ts and the handle hook to observe every SvelteKit request. - Resolve the response before sending crawler telemetry so the final status code can be included. - Keep the server secret in private environment variables. 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: - Start or preview the SvelteKit app. - Inspect the rendered head and Network requests. - Refresh Human Analytics status. - Run the SvelteKit app with a server adapter. - Request a route with curl -A "GPTBot". - Refresh AI Analytics status. ``` ## Research Notes - `src/app.html` is the global HTML template for SvelteKit. - `src/hooks.server.ts` can define a `handle` hook that runs for server requests. - Server hooks do not run for prerendered pages or static assets, even on server deployments. Primary references: - https://svelte.dev/docs/kit/hooks ## Human Analytics Add the script to `src/app.html`. ```html %sveltekit.head%
%sveltekit.body%
``` Best practices: - Keep the script near `%sveltekit.head%`. - Use public env values only for publishable browser keys. - Use the npm SDK from client modules only when custom events are needed. Verification: - Start or preview the app. - Inspect the rendered head and Network requests. - Refresh Human Analytics status. Troubleshooting: - If the script is absent, confirm `src/app.html` is the active template. - If CSP blocks Virent, update deployed CSP headers. - If localhost testing is needed, temporarily add `data-allow-localhost="true"`. ### 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 ``` ## AI Analytics Set private environment values: ```env VIRENT_SITE_ID=site_... VIRENT_INGEST_SECRET=vha_sk_... VIRENT_INGEST_ENDPOINT=https://app.virent.app/v1/ingest/bot ``` Add or compose a server hook: ```ts // src/hooks.server.ts import { env } from "$env/dynamic/private" import type { Handle } from "@sveltejs/kit" 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 const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event) const userAgent = event.request.headers.get("user-agent") ?? "" if (!staticAssetPattern.test(event.url.pathname) && aiCrawlerPattern.test(userAgent)) { await fetch(env.VIRENT_INGEST_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": env.VIRENT_INGEST_SECRET, }, body: JSON.stringify({ siteId: env.VIRENT_SITE_ID, url: event.url.toString(), host: event.url.host, path: event.url.pathname, method: event.request.method, referer: event.request.headers.get("referer"), userAgent, statusCode: response.status, requestId: crypto.randomUUID(), timestamp: new Date().toISOString(), }), }) } return response } ``` Best practices: - Compose with existing auth, i18n, or observability hooks instead of replacing them. - Resolve the response first so the final status code is available. - Use the hosting edge or reverse proxy for prerendered pages, static assets, and static-adapter deployments. Verification: ```sh curl -A "GPTBot" https://your-domain.com/ ``` - Confirm the hook runs. - Refresh AI Analytics status. Troubleshooting: - If hooks do not run, confirm the deployed adapter supports server-side requests. - If existing hooks break, compose handles in sequence. - If secrets are undefined, verify private env loading in the platform. --- # Express Installation Guide > Install Virent Human Analytics and AI Crawler Analytics on Express. Canonical: https://virent.app/docs/installation/express Last updated: 2026-08-26 This is the canonical Virent installation guide for Express applications. Coverage limits: crawler middleware observes only requests handled by this Node.js process. Pages served by a CDN or static host in front of Express need provider logs. Consent, Do Not Track (opt-in) and repeated-initialization rules are in [Supported runtimes and coverage limits](/docs/installation/runtimes-and-coverage). ### Install with your coding agent Paste this prompt into Claude Code, Codex, Cursor or another coding agent. ```text Install Virent analytics on my Express website. Read the canonical guide first and follow its code exactly: https://virent.app/docs/installation/express.md Install two separate things: 1. Human Analytics (browser): Place the script in the common EJS, Pug, Handlebars, or HTML layout. 2. AI Crawler Analytics (server): Add an Express middleware that posts crawler request metadata after responses finish. 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 browser script to the shared HTML template or layout rendered by Express. - Keep the script in the head or at the end of body consistently across all routes. - Use the npm SDK in browser bundles only for custom events. AI Crawler Analytics best practices: - Register the Virent middleware before route handlers so every page request can be observed. - Send telemetry after the response finishes so the final HTTP status code is accurate. - Skip static asset middleware paths and health checks. 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: - Render a page and view source for the Virent script. - Open the page in a browser and check Network requests. - Refresh Human Analytics status. - Run the Express server. - Request a page with curl -A "GPTBot". - Check server logs and refresh Virent status. ``` ## Research Notes - Express middleware is registered with `app.use()` and runs in registration order. - Middleware should call `next()` unless it intentionally ends the request-response cycle. - Express has no fixed template system; Human Analytics belongs in the shared template or HTML partial used by the app. Primary references: - https://expressjs.com/en/5x/guide/writing-middleware/ ## Human Analytics Add the script to your shared template. ```html ``` Best practices: - Add the script to the common layout used by all public pages. - If Express serves a React/Vue bundle, edit the static app `index.html` instead. - Use the npm SDK only in browser assets for custom events. - Update Helmet or reverse proxy CSP headers if present. Verification: - Render a page and view source for the Virent script. - Open the page in a browser and check Network requests. - Refresh Human Analytics status. Troubleshooting: - If only some pages track, identify additional layouts. - If CSP blocks Virent, update Helmet or proxy headers. - If custom event code runs on the server, move it into browser assets. ### 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 ``` ## AI Analytics Set server environment values: ```env VIRENT_SITE_ID=site_... VIRENT_INGEST_SECRET=vha_sk_... VIRENT_INGEST_ENDPOINT=https://app.virent.app/v1/ingest/bot ``` Register middleware before page routes. ```ts import type { NextFunction, Request, Response } from "express" 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 function virentCrawlerAnalytics(req: Request, res: Response, next: NextFunction) { res.on("finish", () => { const userAgent = req.get("user-agent") ?? "" if (staticAssetPattern.test(req.path) || !aiCrawlerPattern.test(userAgent)) { return } void 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: `${req.protocol}://${req.get("host")}${req.originalUrl}`, host: req.get("host"), path: req.path, method: req.method, referer: req.get("referer") ?? null, userAgent, statusCode: res.statusCode, requestId: crypto.randomUUID(), timestamp: new Date().toISOString(), }), }).catch((error) => { console.error("Virent crawler analytics failed", error) }) }) next() } app.use(virentCrawlerAnalytics) ``` Best practices: - Register before route handlers. - Send after `finish` so the final response status is available. - Skip static assets and health checks. - Node 18+ includes `fetch`; older runtimes need an HTTP client. Verification: ```sh curl -A "GPTBot" https://your-domain.com/ ``` - Confirm Express logs the request and posts to Virent. - Refresh AI Analytics status. Troubleshooting: - If no events arrive, confirm `app.use(virentCrawlerAnalytics)` runs before routes. - If static files are counted, add extension exclusions. - If `fetch` is undefined, upgrade Node or use the app's existing HTTP client. --- # Laravel Installation Guide > Install Virent Human Analytics and AI Crawler Analytics on Laravel. Canonical: https://virent.app/docs/installation/laravel Last updated: 2026-08-26 This is the canonical Virent installation guide for Laravel applications. ### Install with your coding agent Paste this prompt into Claude Code, Codex, Cursor or another coding agent. ```text Install Virent analytics on my Laravel website. Read the canonical guide first and follow its code exactly: https://virent.app/docs/installation/laravel.md Install two separate things: 1. Human Analytics (browser): Install the browser script in the shared Blade layout used by public pages. 2. AI Crawler Analytics (server): Create a Laravel middleware class and append it to the web middleware group. 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 once to the shared Blade layout, usually resources/views/layouts/app.blade.php. - Use the publishable key in browser markup only. - Keep the script out of admin-only or partial templates unless those are the only public pages. AI Crawler Analytics best practices: - Add Virent to Laravel's web middleware group so normal web page requests are covered. - Use the Http facade with server-only .env values for crawler telemetry. - Use terminable middleware so telemetry is sent after the application response and includes the final status code. 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 php artisan view:clear if needed. - Open a public page and inspect the head. - Refresh Human Analytics status. - Run php artisan optimize:clear after adding env values. - Request a page with curl -A "GPTBot". - Refresh AI Analytics status. ``` ## Research Notes - Laravel 13.x configures middleware in `bootstrap/app.php`. - Middleware can run before and after `$next($request)`, which makes final response status available. - The HTTP facade is the recommended built-in client for outbound server requests. Primary references: - https://laravel.com/docs/13.x/middleware - https://laravel.com/docs/13.x/http-client ## Human Analytics Add the script to the shared Blade layout. ```blade @vite(['resources/css/app.css', 'resources/js/app.js']) ``` Best practices: - Install in the layout used by public web routes. - Use only the publishable browser key in Blade output. - Add nonce attributes if the app's CSP requires them. - Clear compiled views if the deployed page does not update. Verification: ```sh php artisan view:clear ``` - Open a public page and inspect the head. - Check Network for the Virent script and pageview request. - Refresh Human Analytics status. Troubleshooting: - If some pages are not tracked, find additional Blade layouts. - If CSP blocks Virent, update Laravel or proxy headers. - If cached views hide the change, run `php artisan view:clear`. ### 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 ``` ## AI Analytics Set server values: ```env VIRENT_SITE_ID=site_... VIRENT_INGEST_SECRET=vha_sk_... VIRENT_INGEST_ENDPOINT=https://app.virent.app/v1/ingest/bot ``` Create middleware: ```php userAgent() ?? ''; if ( preg_match('/\.(?:png|jpg|jpeg|gif|svg|ico|webp|css|js|map|txt|xml)$/i', $request->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', $userAgent) ) { return; } try { Http::withHeaders([ 'x-api-key' => env('VIRENT_INGEST_SECRET'), ])->timeout(2)->post(env('VIRENT_INGEST_ENDPOINT'), [ 'siteId' => env('VIRENT_SITE_ID'), 'url' => $request->fullUrl(), 'host' => $request->getHost(), 'path' => '/' . ltrim($request->path(), '/'), 'method' => $request->method(), 'referer' => $request->headers->get('referer'), 'userAgent' => $userAgent, 'statusCode' => $response->getStatusCode(), 'requestId' => (string) str()->uuid(), 'timestamp' => now()->toIso8601String(), ]); } catch (\Throwable) { // Analytics must never change the application response. } } } ``` Register it: ```php // bootstrap/app.php use App\Http\Middleware\TrackVirentCrawler; use Illuminate\Foundation\Configuration\Middleware; ->withMiddleware(function (Middleware $middleware): void { $middleware->web(append: [ TrackVirentCrawler::class, ]); }) ``` Best practices: - Append to Laravel's `web` middleware group for public page routes. - Do not include API routes unless AI crawler traffic to APIs should be tracked. - Use terminable middleware so telemetry is sent after the application response with its final status. - Clear config cache after env changes. Verification: ```sh php artisan optimize:clear curl -A "GPTBot" https://your-domain.com/ ``` - Confirm Laravel sends an outbound request to Virent. - Refresh AI Analytics status. Troubleshooting: - If middleware does not run, confirm it is appended in `bootstrap/app.php`. - If env values are missing, clear config cache. - If high-traffic pages slow down, lower timeout values or queue telemetry. --- # WordPress Installation Guide > Install Virent Human Analytics and AI Crawler Analytics on WordPress. Canonical: https://virent.app/docs/installation/wordpress Last updated: 2026-08-26 This is the canonical Virent installation guide for WordPress sites. ### Install with your coding agent Paste this prompt into Claude Code, Codex, Cursor or another coding agent. ```text Install Virent analytics on my WordPress website. Read the canonical guide first and follow its code exactly: https://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 `shutdown` hook runs late enough to read the final WordPress response status. - `wp_remote_post` performs 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 ``` ## AI Analytics Keep server values in `wp-config.php` or environment-specific configuration. ```php 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 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_SECRET` outside rendered HTML. - Confirm the host allows outbound HTTP requests to Virent. Verification: ```sh 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. --- # Capture AI crawlers from your host or CDN. > Connect Vercel, Cloudflare, AWS CloudFront, Akamai, Netlify, Google Cloud, Fastly, Framer or Webflow to Virent AI Crawler Analytics, with the same steps as the dashboard. Canonical: https://virent.app/docs/integrations/overview Last updated: 2026-10-19 AI crawlers never run your page's JavaScript. If your site runs on a host or CDN, its request logs or an edge Worker can report crawler visits to Virent without changing your application code. ## Choose your host - [Vercel](/docs/integrations/vercel) - [Cloudflare](/docs/integrations/cloudflare) - [AWS CloudFront](/docs/integrations/aws-cloudfront) - [Akamai](/docs/integrations/akamai) - [Netlify](/docs/integrations/netlify) - [Google Cloud](/docs/integrations/google-cloud) - [Fastly](/docs/integrations/fastly) - [Framer](/docs/integrations/framer) - [Webflow](/docs/integrations/webflow) Each page has the same steps as **Connect analytics → Hosting integrations** in the dashboard, which fills in your site ID and domain. If you control the server that renders your pages, a [framework guide](/docs#installation) is an alternative. ## Logs or code | | Log-based (Log Drains, Logpush, CloudFront, DataStream 2, Netlify, Google Cloud, Fastly) | Edge Worker or middleware | | --- | --- | --- | | Sees CDN-cached pages | Yes | Workers yes; middleware only sees requests that reach your app | | Sees the final response status | Yes | Workers yes; middleware runs before the response | | Changes to your site | None; the host sends logs | A Worker in front of the site, or a `proxy.ts` file | | Plan requirements | Often an enterprise or paid plan on the host | Available on most plans | See [Runtimes and coverage](/docs/installation/runtimes-and-coverage) for the details of each runtime. ## Before you start - Your **site ID** and **server secret** (`vha_sk_…`) are in **Settings → Connection** and in the Connect analytics dialog. - The secret is shown once, after **Rotate + reveal**. Rotating stops the old secret, so update existing installs. See [Keys and secrets](/docs/workspace/keys). - Keep the secret in your host's secret store. Never put it in page code or commit it. ## After setup Every page ends the same way: send a [test crawler request](/docs/analytics/ai-crawlers#verify) to your site and watch the setup dialog, which shows "Virent is receiving AI crawler traffic" once the first request arrives. Only AI crawler requests are stored and count toward your plan; search indexers, SEO tools and monitoring are dropped on arrival. --- # Capture AI crawlers on Vercel. > Connect a Vercel site to Virent AI Crawler Analytics with a Log Drain (Pro and Enterprise) or Next.js middleware (any plan). Canonical: https://virent.app/docs/integrations/vercel Last updated: 2026-10-19 A Log Drain sends every request, including CDN-cached pages, without running your code. Middleware works on any plan but only sees requests that reach your app. ## Choose a method | Method | Plans | Coverage | | --- | --- | --- | | [Log Drains](#log-drains) (recommended on Pro+) | Pro and Enterprise | Best coverage: includes CDN-cached pages without running application code | | [Middleware](#middleware) | Any plan | Runs per matched request in Next.js 16+ `proxy.ts`; does not replace CDN request logs | You need your site ID and server secret from **Settings → Connection** (see [Hosting integrations](/docs/integrations/overview#before-you-start)). In the dashboard, **Connect analytics → Hosting integrations → Vercel** shows these steps with your values filled in. ## Log Drains ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Configure a Vercel Log Drain so example.com sends request logs to Virent AI crawler analytics. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Steps: 1. In the Vercel dashboard, add a Logs drain for the project serving example.com. 2. Name it Virent Crawler Logs. Select that specific project. 3. Sources: Functions, Edge Functions, Static Files, Rewrites, Redirects. Environment: Production. 4. Destination: Custom Endpoint https://virent.app/api/ingest/vercel 5. Add an Authorization header with value: Bearer 6. Keep delivery at 100% with no sampling rules, create the drain, then send a crawler request to example.com. Do not commit the server secret. ``` ### Choose data to drain Open your team's drain settings in the [Vercel dashboard](https://vercel.com/dashboard). Click **Add Drain**, select **Logs**, then click **Next**. ### Configure the drain | Setting | Value | | --- | --- | | Drain name | `Virent Crawler Logs` | | Projects | **Specific Projects**: pick the project serving your site | | Sources | Functions, Edge Functions, Static Files, Rewrites, Redirects | | Environments | Production | You do not need sampling rules. Continue with the defaults after selecting the project, sources and production environment. ### Configure the destination Select **Custom Endpoint**, paste this URL, add a custom `Authorization` header with the value below (your server secret after `Bearer`), then click **Test**. ```text https://virent.app/api/ingest/vercel ``` ```text Bearer ``` ### Create the drain Keep delivery at 100% with no sampling rules, then click **Create Drain** at the end of the wizard. That is everything on Vercel's side. Send a [test crawler request](/docs/analytics/ai-crawlers#verify) to your site to confirm. ## Middleware For Next.js 16+ on any Vercel plan. The [Next.js guide](/docs/installation/nextjs) covers the same proxy together with Human Analytics. ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Install Virent AI crawler analytics on example.com with Vercel middleware (Next.js proxy.ts). Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Steps: 1. Run npm install @virent.app/sdk@^0.3.0 in the project serving the site. 2. Add proxy.ts at the project root, or src/proxy.ts if the app uses a src directory. Use createVirentBotProxy with endpoint: process.env.VIRENT_INGEST_ENDPOINT and report in event.waitUntil so the response is never blocked. Do not rely on the SDK default endpoint; use the exact Virent environment below. 3. Set these environment variables locally and in Vercel: VIRENT_SITE_ID= VIRENT_INGEST_SECRET= VIRENT_INGEST_ENDPOINT=https://virent.app/v1/ingest/bot 4. Deploy the site to Vercel, then send a crawler request to example.com. Confirm the ingest request is accepted and appears in this Virent environment; an HTTP 200 from the website alone does not verify analytics delivery. This is server-side crawler tracking, not browser analytics. Do not hard-code the secret. ``` ### Install the package Run this in the project serving your site: ```sh npm install @virent.app/sdk ``` ### Add the proxy Create `proxy.ts` at the project root, or inside `src` if the project uses a `src` directory. The helper reports in `event.waitUntil`, after the response path is released. ```typescript // proxy.ts import { createVirentBotProxy } from "@virent.app/sdk/next" export const proxy = createVirentBotProxy({ siteId: "", writeKey: process.env.VIRENT_INGEST_SECRET!, endpoint: process.env.VIRENT_INGEST_ENDPOINT || "https://virent.app/v1/ingest/bot", trustedProxy: "vercel", }) export const config = { matcher: [ "/((?!api|_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml|.*\\.(?:png|jpg|jpeg|gif|svg|ico|webp|css|js|map)$).*)", ], } ``` ### Set environment variables Add these values locally and in **Settings → Environment Variables** on Vercel, so the deployed site can report securely. ```env VIRENT_SITE_ID= VIRENT_INGEST_SECRET= VIRENT_INGEST_ENDPOINT=https://virent.app/v1/ingest/bot ``` ### Deploy Push to GitHub or deploy from the Vercel CLI, then send a [test crawler request](/docs/analytics/ai-crawlers#verify). ```sh vercel deploy --prod ``` --- # Capture AI crawlers on Cloudflare. > Connect a Cloudflare zone to Virent AI Crawler Analytics with a Worker (most sites) or Logpush (Enterprise). Canonical: https://virent.app/docs/integrations/cloudflare Last updated: 2026-10-19 A Worker reports AI crawlers from a proxied zone without blocking responses, on any plan. On Enterprise, Logpush sends complete edge logs, including cached responses, with no code. ## Choose a method | Method | Plans | Coverage | | --- | --- | --- | | [Workers](#workers) (most sites) | Any plan | Reports supported AI crawlers from a proxied zone without blocking responses | | [Logpush](#logpush) (recommended on Enterprise) | Enterprise | Passive, complete edge-log coverage, including cached responses | Both need the site's DNS record proxied (orange cloud). You need your site ID and server secret from **Settings → Connection** (see [Hosting integrations](/docs/integrations/overview#before-you-start)). In the dashboard, **Connect analytics → Hosting integrations → Cloudflare** shows these steps with your values filled in. ## Workers ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Install Virent AI crawler analytics on example.com with a Cloudflare Worker. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Steps: 1. Create a Worker in the Cloudflare dashboard. 2. Replace the starter code with: ```javascript const SITE_ID = "" const INGEST = "https://virent.app/v1/ingest/bot" // Send eligible requests for classification by Virent. const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/i export default { async fetch(request, env, ctx) { const response = await fetch(request) ctx.waitUntil(report(request, response, env.VIRENT_INGEST_SECRET).catch(() => {})) return response }, } async function report(request, response, secret) { if (request.method !== "GET") return const url = new URL(request.url) const userAgent = request.headers.get("user-agent") || "" if (ASSET.test(url.pathname)) return const cf = request.cf || {} await fetch(INGEST, { method: "POST", headers: { "content-type": "application/json", "x-api-key": secret, }, body: JSON.stringify({ siteId: SITE_ID, url: url.origin + url.pathname, host: url.host, path: url.pathname, query: {}, method: request.method, statusCode: response.status, userAgent, accept: request.headers.get("accept"), acceptLanguage: request.headers.get("accept-language"), referer: null, country: cf.country || null, requestId: request.headers.get("cf-ray") || crypto.randomUUID(), timestamp: new Date().toISOString(), }), }) } ``` 3. Add a route of *example.com/* on the zone serving the site. 4. Under DNS → Records, keep the site A, AAAA, or CNAME record proxied (orange cloud). Reporting must run in ctx.waitUntil. Do not hard-code the secret in a committed repo if you can use Worker secrets instead. ``` ### Create a Worker In the [Cloudflare dashboard](https://dash.cloudflare.com), open Workers, click **Create application**, start with **Hello World**, choose any Worker name, then deploy it. ### Store the connection secret Run this for the Worker and paste your Virent server secret when prompted. The secret stays out of the Worker source. ```sh npx wrangler secret put VIRENT_INGEST_SECRET ``` ### Paste the tracking code Open **Edit code**, replace the starter code with this snippet and your site ID, and deploy again. Reporting runs in `ctx.waitUntil` and never blocks the site response. ```javascript const SITE_ID = "" const INGEST = "https://virent.app/v1/ingest/bot" // Send eligible requests for classification by Virent. const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/i export default { async fetch(request, env, ctx) { const response = await fetch(request) ctx.waitUntil(report(request, response, env.VIRENT_INGEST_SECRET).catch(() => {})) return response }, } async function report(request, response, secret) { if (request.method !== "GET") return const url = new URL(request.url) const userAgent = request.headers.get("user-agent") || "" if (ASSET.test(url.pathname)) return const cf = request.cf || {} await fetch(INGEST, { method: "POST", headers: { "content-type": "application/json", "x-api-key": secret, }, body: JSON.stringify({ siteId: SITE_ID, url: url.origin + url.pathname, host: url.host, path: url.pathname, query: {}, method: request.method, statusCode: response.status, userAgent, accept: request.headers.get("accept"), acceptLanguage: request.headers.get("accept-language"), referer: null, country: cf.country || null, requestId: request.headers.get("cf-ray") || crypto.randomUUID(), timestamp: new Date().toISOString(), }), }) } ``` ### Route your domain through it On the Worker, open **Domains**, add a **Route** such as `*example.com/*`, and point it at the zone serving your site. ### Verify your proxy status Under **DNS → Records**, make sure the site's A, AAAA or CNAME record has the orange cloud and is set to **Proxied**. Gray-cloud traffic bypasses the Worker. Then send a [test crawler request](/docs/analytics/ai-crawlers#verify). ## Logpush ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Configure Cloudflare Logpush so example.com sends HTTP request logs to Virent AI crawler analytics. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Steps: 1. In the example.com zone, create a Logpush job with HTTP destination https://virent.app/api/ingest/cloudflare-logpush?header_x-api-key=%3Cpaste-your-server-secret%3E. 2. Dataset: HTTP requests. 3. Job name: Virent Crawler Logs. 4. Fields: ClientRequestHost, ClientRequestMethod, ClientRequestURI, EdgeResponseStatus, EdgeStartTimestamp, RayID, ClientRequestUserAgent, ClientRequestReferer, ClientIP, ClientCountry, WorkerSubrequest. 5. Keep DNS proxied (orange cloud). WorkerSubrequest lets Virent ignore the site's own Worker subrequests. Do not commit the server secret. ``` ### Select a destination In your site's zone, create a Logpush job, select **HTTP destination**, paste this endpoint and continue. Replace the `header_x-api-key` value with your server secret (URL-encoded); the dashboard fills it in after **Rotate + reveal**. ```text https://virent.app/api/ingest/cloudflare-logpush?header_x-api-key=%3Cpaste-your-server-secret%3E ``` ### Select the dataset Choose **HTTP requests**. ### Configure the Logpush job | Setting | Value | | --- | --- | | Job name | `Virent Crawler Logs` | | Fields | `ClientRequestHost`, `ClientRequestMethod`, `ClientRequestURI`, `EdgeResponseStatus`, `EdgeStartTimestamp`, `RayID`, `ClientRequestUserAgent`, `ClientRequestReferer`, `ClientIP`, `ClientCountry`, `WorkerSubrequest` | Keep the sampling rate at 1.0 (100%). `WorkerSubrequest` lets Virent ignore requests made by your own Workers so they are not counted twice. Raw client IPs are hashed immediately and never stored. ### Verify your proxy status Under **DNS → Records**, make sure the site's A, AAAA or CNAME record has the orange cloud and is set to **Proxied**. Then send a [test crawler request](/docs/analytics/ai-crawlers#verify). --- # Capture AI crawlers on AWS CloudFront. > Connect AWS CloudFront to Virent AI Crawler Analytics. Stream 100% sampled CloudFront request logs through Kinesis and a small Lambda consumer. Canonical: https://virent.app/docs/integrations/aws-cloudfront Last updated: 2026-10-19 Stream 100% sampled CloudFront request logs through Kinesis and a small Lambda consumer. CloudFront real-time logs go to a Kinesis Data Stream, and a small Lambda function forwards page requests to Virent. Real-time delivery is best-effort; keep standard access logs for forensic reconciliation. You need your site ID and server secret from **Settings → Connection** (see [Hosting integrations](/docs/integrations/overview#before-you-start)). In the dashboard, **Connect analytics → Hosting integrations → AWS CloudFront** shows these steps with your site ID, domain and secret filled in. Below, replace ``, `` and `example.com` with your own values. ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Configure AWS CloudFront so example.com sends reliable AI crawler request telemetry to Virent. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Use the current provider documentation: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/real-time-logs.html Steps: 1. Create the Kinesis destination: Create a Kinesis Data Stream in the same AWS Region where you will create the CloudFront real-time log configuration. Grant CloudFront permission to write to it. 2. Add the Lambda consumer: Create a Node.js 22 Lambda subscribed to the stream. Set VIRENT_INGEST_SECRET to the revealed connection secret and allow outbound HTTPS to https://virent.app/api/ingest/http. const INGEST = "https://virent.app/api/ingest/http" const SITE_ID = "" export const handler = async (event) => { const events = event.Records.flatMap(({ kinesis }) => Buffer.from(kinesis.data, "base64") .toString("utf8") .trim() .split("\n") .filter(Boolean) .map((line) => line.split("\t")) .filter((fields) => ["GET", "HEAD"].includes(fields[3] || "")) .map((fields) => ({ timestamp: new Date(Number(fields[0]) * 1000).toISOString(), client_ip: fields[1], status_code: Number(fields[2]), request_method: fields[3], hostname: fields[4], request_path: fields[5], query_string: null, user_agent: fields[7], referrer: null, content_type: "", })) ) for (let offset = 0; offset < events.length; offset += 1000) { const response = await fetch(INGEST, { method: "POST", headers: { "content-type": "application/json", "x-api-key": process.env.VIRENT_INGEST_SECRET, }, body: JSON.stringify(events.slice(offset, offset + 1000)), }) if (!response.ok) throw new Error(`Virent ingest failed: ${response.status}`) } return { siteId: SITE_ID, submitted: events.length } } 3. Configure 100% request logging: Create a CloudFront real-time log configuration with a 100% sampling rate and these fields in exactly this order. Associate it with every cache behavior that serves public pages. timestamp c-ip sc-status cs-method cs-host cs-uri-stem cs-uri-query cs(User-Agent) cs(Referer) x-edge-request-id 4. Activate and verify: Activate the distribution changes, request https://example.com/ with a supported AI crawler user agent, then confirm Virent receives the visit. CloudFront real-time delivery is best-effort, so use standard access logs for forensic reconciliation. Keep the secret server-side, preserve 100% request coverage where the provider supports sampling, and verify both normal site delivery and a crawler request after activation. ``` ## Steps 1. **Create the Kinesis destination**: Create a Kinesis Data Stream in the same AWS Region where you will create the CloudFront real-time log configuration. Grant CloudFront permission to write to it. 2. **Add the Lambda consumer**: Create a Node.js 22 Lambda subscribed to the stream. Set VIRENT_INGEST_SECRET to the revealed connection secret and allow outbound HTTPS to https://virent.app/api/ingest/http. ```javascript const INGEST = "https://virent.app/api/ingest/http" const SITE_ID = "" export const handler = async (event) => { const events = event.Records.flatMap(({ kinesis }) => Buffer.from(kinesis.data, "base64") .toString("utf8") .trim() .split("\n") .filter(Boolean) .map((line) => line.split("\t")) .filter((fields) => ["GET", "HEAD"].includes(fields[3] || "")) .map((fields) => ({ timestamp: new Date(Number(fields[0]) * 1000).toISOString(), client_ip: fields[1], status_code: Number(fields[2]), request_method: fields[3], hostname: fields[4], request_path: fields[5], query_string: null, user_agent: fields[7], referrer: null, content_type: "", })) ) for (let offset = 0; offset < events.length; offset += 1000) { const response = await fetch(INGEST, { method: "POST", headers: { "content-type": "application/json", "x-api-key": process.env.VIRENT_INGEST_SECRET, }, body: JSON.stringify(events.slice(offset, offset + 1000)), }) if (!response.ok) throw new Error(`Virent ingest failed: ${response.status}`) } return { siteId: SITE_ID, submitted: events.length } } ``` 3. **Configure 100% request logging**: Create a CloudFront real-time log configuration with a 100% sampling rate and these fields in exactly this order. Associate it with every cache behavior that serves public pages. ```text timestamp c-ip sc-status cs-method cs-host cs-uri-stem cs-uri-query cs(User-Agent) cs(Referer) x-edge-request-id ``` 4. **Activate and verify**: Activate the distribution changes, request https://example.com/ with a supported AI crawler user agent, then confirm Virent receives the visit. CloudFront real-time delivery is best-effort, so use standard access logs for forensic reconciliation. Check AWS CloudFront's [current documentation](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/real-time-logs.html) if its screens differ from these steps. ## Verify Send a [test crawler request](/docs/analytics/ai-crawlers#verify) to your site. The setup dialog in Virent shows "Virent is receiving AI crawler traffic" once the first request arrives. --- # Capture AI crawlers on Akamai. > Connect Akamai to Virent AI Crawler Analytics. Send DataStream 2 JSON request logs directly to Virent over authenticated HTTPS. Canonical: https://virent.app/docs/integrations/akamai Last updated: 2026-10-19 Send DataStream 2 JSON request logs directly to Virent over authenticated HTTPS. DataStream 2 sends JSON request logs straight to Virent over HTTPS, so cached responses are covered without code on your origin. You need your site ID and server secret from **Settings → Connection** (see [Hosting integrations](/docs/integrations/overview#before-you-start)). In the dashboard, **Connect analytics → Hosting integrations → Akamai** shows these steps with your site ID, domain and secret filled in. Below, replace ``, `` and `example.com` with your own values. ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Configure Akamai so example.com sends reliable AI crawler request telemetry to Virent. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Use the current provider documentation: https://techdocs.akamai.com/datastream2/docs/stream-custom-https Steps: 1. Create the HTTPS destination: Create a DataStream 2 stream with a Custom HTTPS destination and JSON output. Use 30-second delivery for the freshest dashboard data. https://virent.app/api/ingest/akamai 2. Authenticate delivery: Add this supported custom request header. Virent acknowledges Akamai’s access_validation payload during destination validation without recording it as traffic. x-api-key: 3. Select request fields: Select these DataStream 2 fields and keep the output format as JSON. Virent decodes Akamai’s URL-encoded user-agent and referrer values. reqId, reqTimeSec, cliIP, statusCode, proto, reqHost, reqMethod, reqPath, rspContentType, UA, queryStr, referer, country 4. Activate and verify: Activate the stream for the example.com property, send a supported AI crawler request, and verify the connection status in Virent. Keep the secret server-side, preserve 100% request coverage where the provider supports sampling, and verify both normal site delivery and a crawler request after activation. ``` ## Steps 1. **Create the HTTPS destination**: Create a DataStream 2 stream with a Custom HTTPS destination and JSON output. Use 30-second delivery for the freshest dashboard data. ```text https://virent.app/api/ingest/akamai ``` 2. **Authenticate delivery**: Add this supported custom request header. Virent acknowledges Akamai’s access_validation payload during destination validation without recording it as traffic. ```text x-api-key: ``` 3. **Select request fields**: Select these DataStream 2 fields and keep the output format as JSON. Virent decodes Akamai’s URL-encoded user-agent and referrer values. ```text reqId, reqTimeSec, cliIP, statusCode, proto, reqHost, reqMethod, reqPath, rspContentType, UA, queryStr, referer, country ``` 4. **Activate and verify**: Activate the stream for the example.com property, send a supported AI crawler request, and verify the connection status in Virent. Check Akamai's [current documentation](https://techdocs.akamai.com/datastream2/docs/stream-custom-https) if its screens differ from these steps. ## Verify Send a [test crawler request](/docs/analytics/ai-crawlers#verify) to your site. The setup dialog in Virent shows "Virent is receiving AI crawler traffic" once the first request arrives. --- # Capture AI crawlers on Netlify. > Connect Netlify to Virent AI Crawler Analytics. Use Netlify's Enterprise Site Traffic Log Drain for complete CDN-side request coverage. Canonical: https://virent.app/docs/integrations/netlify Last updated: 2026-10-19 Use Netlify's Enterprise Site Traffic Log Drain for complete CDN-side request coverage. Log Drains are available on Netlify Enterprise. A Site Traffic drain covers every request Netlify's CDN serves, including cached pages. You need your site ID and server secret from **Settings → Connection** (see [Hosting integrations](/docs/integrations/overview#before-you-start)). In the dashboard, **Connect analytics → Hosting integrations → Netlify** shows these steps with your site ID, domain and secret filled in. Below, replace ``, `` and `example.com` with your own values. ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Configure Netlify so example.com sends reliable AI crawler request telemetry to Virent. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Use the current provider documentation: https://docs.netlify.com/manage/monitoring/log-drains/ Steps: 1. Create the Site Traffic drain: On a Netlify Enterprise site, create a Log Drain, choose General HTTP endpoint, and select Site Traffic logs. https://virent.app/api/ingest/netlify 2. Keep required request fields: Add the Authorization header. Do not enable Exclude PII: Virent needs client_ip and user_agent for bot classification and hashes the IP before storage. Authorization: Bearer 3. Enable complete delivery: Use JSON or NDJSON delivery and leave filtering off so CDN-cached pages and every supported AI crawler reach Virent. 4. Activate and verify: Publish the drain, request https://example.com/ as an AI crawler, and verify that Virent reports the connection. Keep the secret server-side, preserve 100% request coverage where the provider supports sampling, and verify both normal site delivery and a crawler request after activation. ``` ## Steps 1. **Create the Site Traffic drain**: On a Netlify Enterprise site, create a Log Drain, choose General HTTP endpoint, and select Site Traffic logs. ```text https://virent.app/api/ingest/netlify ``` 2. **Keep required request fields**: Add the Authorization header. Do not enable Exclude PII: Virent needs client_ip and user_agent for bot classification and hashes the IP before storage. ```text Authorization: Bearer ``` 3. **Enable complete delivery**: Use JSON or NDJSON delivery and leave filtering off so CDN-cached pages and every supported AI crawler reach Virent. 4. **Activate and verify**: Publish the drain, request https://example.com/ as an AI crawler, and verify that Virent reports the connection. Check Netlify's [current documentation](https://docs.netlify.com/manage/monitoring/log-drains/) if its screens differ from these steps. ## Verify Send a [test crawler request](/docs/analytics/ai-crawlers#verify) to your site. The setup dialog in Virent shows "Virent is receiving AI crawler traffic" once the first request arrives. --- # Capture AI crawlers on Google Cloud. > Connect Google Cloud to Virent AI Crawler Analytics. Export 100% sampled external load-balancer request logs through Pub/Sub push delivery. Canonical: https://virent.app/docs/integrations/google-cloud Last updated: 2026-10-19 Export 100% sampled external load-balancer request logs through Pub/Sub push delivery. For sites behind a global external Application Load Balancer. Request logs go through Cloud Logging and a Pub/Sub push subscription to Virent. The push URL carries a token: replace its value with your server secret (URL-encoded); the dashboard fills it in after **Rotate + reveal**. You need your site ID and server secret from **Settings → Connection** (see [Hosting integrations](/docs/integrations/overview#before-you-start)). In the dashboard, **Connect analytics → Hosting integrations → Google Cloud** shows these steps with your site ID, domain and secret filled in. Below, replace ``, `` and `example.com` with your own values. ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Configure Google Cloud so example.com sends reliable AI crawler request telemetry to Virent. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Use the current provider documentation: https://docs.cloud.google.com/load-balancing/docs/https/https-logging-monitoring Steps: 1. Enable 100% load-balancer logs: Enable request logging on every backend service behind the global external Application Load Balancer and set the logging sample rate to 1.0 (100%). 2. Export matching request logs: Create a Cloud Logging sink to a Pub/Sub topic with this filter. Grant the sink writer identity permission to publish to the topic. resource.type="http_load_balancer" httpRequest.requestUrl:"example.com" 3. Create push delivery: Create a Pub/Sub push subscription using this HTTPS endpoint. The token is in the URL because Pub/Sub push subscriptions do not support arbitrary custom authorization headers; rotate the Virent secret if the URL is exposed. https://virent.app/api/ingest/google-cloud?token=%3Cpaste-your-server-secret%3E 4. Activate and verify: Send an AI crawler request to example.com, confirm the subscription is acknowledged, and verify the event in Virent. Cloud Logging exports are usually delivered within seconds but are not synchronous. Keep the secret server-side, preserve 100% request coverage where the provider supports sampling, and verify both normal site delivery and a crawler request after activation. ``` ## Steps 1. **Enable 100% load-balancer logs**: Enable request logging on every backend service behind the global external Application Load Balancer and set the logging sample rate to 1.0 (100%). 2. **Export matching request logs**: Create a Cloud Logging sink to a Pub/Sub topic with this filter. Grant the sink writer identity permission to publish to the topic. ```text resource.type="http_load_balancer" httpRequest.requestUrl:"example.com" ``` 3. **Create push delivery**: Create a Pub/Sub push subscription using this HTTPS endpoint. The token is in the URL because Pub/Sub push subscriptions do not support arbitrary custom authorization headers; rotate the Virent secret if the URL is exposed. ```text https://virent.app/api/ingest/google-cloud?token=%3Cpaste-your-server-secret%3E ``` 4. **Activate and verify**: Send an AI crawler request to example.com, confirm the subscription is acknowledged, and verify the event in Virent. Cloud Logging exports are usually delivered within seconds but are not synchronous. Check Google Cloud's [current documentation](https://docs.cloud.google.com/load-balancing/docs/https/https-logging-monitoring) if its screens differ from these steps. ## Verify Send a [test crawler request](/docs/analytics/ai-crawlers#verify) to your site. The setup dialog in Virent shows "Virent is receiving AI crawler traffic" once the first request arrives. --- # Capture AI crawlers on Fastly. > Connect Fastly to Virent AI Crawler Analytics. Stream request logs from a Fastly CDN service to Virent's authenticated HTTPS endpoint. Canonical: https://virent.app/docs/integrations/fastly Last updated: 2026-10-19 Stream request logs from a Fastly CDN service to Virent's authenticated HTTPS endpoint. An HTTPS logging endpoint on your Fastly service streams one JSON line per request to Virent, including cached responses. You need your site ID and server secret from **Settings → Connection** (see [Hosting integrations](/docs/integrations/overview#before-you-start)). In the dashboard, **Connect analytics → Hosting integrations → Fastly** shows these steps with your site ID, domain and secret filled in. Below, replace ``, `` and `example.com` with your own values. ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Configure Fastly so example.com sends reliable AI crawler request telemetry to Virent. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Use the current provider documentation: https://www.fastly.com/documentation/guides/integrations/logging-endpoints/protocol-based-and-self-hosted/log-streaming-https/ Steps: 1. Create an HTTPS endpoint: On the Fastly CDN service, add an HTTPS logging endpoint. Virent answers Fastly’s ownership validation challenge at this destination. https://virent.app/api/ingest/fastly 2. Authenticate delivery: Set Content type to application/x-ndjson and configure this custom header. Keep Placement on Format Version Default. x-api-key: 3. Set the request log format: Paste this exact log format. It emits one Virent-compatible JSON object per request and safely escapes request headers. {"timestamp":"%{begin:%Y-%m-%dT%H:%M:%SZ}t","status_code":%>s,"request_method":"%m","request_path":"%{json.escape(req.url.path)}V","query_string":"%{json.escape(req.url.qs)}V","content_type":"%{json.escape(resp.http.Content-Type)}V","client_ip":"%a","hostname":"%{json.escape(req.http.host)}V","user_agent":"%{json.escape(req.http.User-Agent)}V","referrer":"%{json.escape(req.http.Referer)}V"} 4. Activate and verify: Create the endpoint, activate the service version on Production, send an AI crawler request to example.com, and verify it in Virent. Keep the secret server-side, preserve 100% request coverage where the provider supports sampling, and verify both normal site delivery and a crawler request after activation. ``` ## Steps 1. **Create an HTTPS endpoint**: On the Fastly CDN service, add an HTTPS logging endpoint. Virent answers Fastly’s ownership validation challenge at this destination. ```text https://virent.app/api/ingest/fastly ``` 2. **Authenticate delivery**: Set Content type to application/x-ndjson and configure this custom header. Keep Placement on Format Version Default. ```text x-api-key: ``` 3. **Set the request log format**: Paste this exact log format. It emits one Virent-compatible JSON object per request and safely escapes request headers. ```text {"timestamp":"%{begin:%Y-%m-%dT%H:%M:%SZ}t","status_code":%>s,"request_method":"%m","request_path":"%{json.escape(req.url.path)}V","query_string":"%{json.escape(req.url.qs)}V","content_type":"%{json.escape(resp.http.Content-Type)}V","client_ip":"%a","hostname":"%{json.escape(req.http.host)}V","user_agent":"%{json.escape(req.http.User-Agent)}V","referrer":"%{json.escape(req.http.Referer)}V"} ``` 4. **Activate and verify**: Create the endpoint, activate the service version on Production, send an AI crawler request to example.com, and verify it in Virent. Check Fastly's [current documentation](https://www.fastly.com/documentation/guides/integrations/logging-endpoints/protocol-based-and-self-hosted/log-streaming-https/) if its screens differ from these steps. ## Verify Send a [test crawler request](/docs/analytics/ai-crawlers#verify) to your site. The setup dialog in Virent shows "Virent is receiving AI crawler traffic" once the first request arrives. --- # Capture AI crawlers on a Framer site. > Connect Framer to Virent AI Crawler Analytics. Advanced reverse-proxy setup for sites on an eligible Framer plan using a Cloudflare Worker. Canonical: https://virent.app/docs/integrations/framer Last updated: 2026-10-19 Advanced reverse-proxy setup for sites on an eligible Framer plan using a Cloudflare Worker. Framer has no request logs or server code, so a Cloudflare Worker in front of the site proxies requests to Framer and reports AI crawlers. This is an advanced setup for sites on a Framer plan that allows reverse proxying; it is not recommended for ordinary Framer custom domains. You need your site ID and server secret from **Settings → Connection** (see [Hosting integrations](/docs/integrations/overview#before-you-start)). In the dashboard, **Connect analytics → Hosting integrations → Framer** shows these steps with your site ID, domain and secret filled in. Below, replace ``, `` and `example.com` with your own values. ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Configure Framer so example.com sends reliable AI crawler request telemetry to Virent. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Use the current provider documentation: https://www.framer.com/help/articles/how-to-proxy-with-cloudflare/ Steps: 1. Confirm Framer eligibility: Confirm the site is on an eligible Framer plan for reverse proxying. Keep its free Framer subdomain published; it becomes the Worker origin. This advanced method is not recommended for ordinary Framer custom domains. 2. Create the reverse-proxy Worker: Create a Cloudflare Worker with this code. Add VIRENT_INGEST_SECRET as a Worker secret and FRAMER_ORIGIN as the hostname of the free Framer subdomain, without https://. const SITE_ID = "" const INGEST = "https://virent.app/v1/ingest/bot" const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/i export default { async fetch(request, env, ctx) { const publicUrl = new URL(request.url) const originUrl = new URL(request.url) originUrl.hostname = env.FRAMER_ORIGIN const response = await fetch(new Request(originUrl, request)) const userAgent = request.headers.get("user-agent") || "" if (!ASSET.test(publicUrl.pathname) && ["GET", "HEAD"].includes(request.method)) { ctx.waitUntil(fetch(INGEST, { method: "POST", headers: { "content-type": "application/json", "x-api-key": env.VIRENT_INGEST_SECRET, }, body: JSON.stringify({ siteId: SITE_ID, url: publicUrl.origin + publicUrl.pathname, host: publicUrl.host, path: publicUrl.pathname, query: {}, method: request.method, statusCode: response.status, userAgent, referer: null, country: request.cf?.country || null, requestId: request.headers.get("cf-ray") || crypto.randomUUID(), timestamp: new Date().toISOString(), }), }).catch(() => {})) } return response }, } 3. Route the custom domain: Follow Framer’s Cloudflare proxy guide to create the dummy proxied DNS record, bind the Worker route for *example.com/*, and set the canonical URL in Framer. 4. Activate and verify: Activate the Worker, verify normal pages and assets still load from Framer, then send an AI crawler request and confirm it appears in Virent. Keep the secret server-side, preserve 100% request coverage where the provider supports sampling, and verify both normal site delivery and a crawler request after activation. ``` ## Steps 1. **Confirm Framer eligibility**: Confirm the site is on an eligible Framer plan for reverse proxying. Keep its free Framer subdomain published; it becomes the Worker origin. This advanced method is not recommended for ordinary Framer custom domains. 2. **Create the reverse-proxy Worker**: Create a Cloudflare Worker with this code. Add VIRENT_INGEST_SECRET as a Worker secret and FRAMER_ORIGIN as the hostname of the free Framer subdomain, without https://. ```javascript const SITE_ID = "" const INGEST = "https://virent.app/v1/ingest/bot" const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/i export default { async fetch(request, env, ctx) { const publicUrl = new URL(request.url) const originUrl = new URL(request.url) originUrl.hostname = env.FRAMER_ORIGIN const response = await fetch(new Request(originUrl, request)) const userAgent = request.headers.get("user-agent") || "" if (!ASSET.test(publicUrl.pathname) && ["GET", "HEAD"].includes(request.method)) { ctx.waitUntil(fetch(INGEST, { method: "POST", headers: { "content-type": "application/json", "x-api-key": env.VIRENT_INGEST_SECRET, }, body: JSON.stringify({ siteId: SITE_ID, url: publicUrl.origin + publicUrl.pathname, host: publicUrl.host, path: publicUrl.pathname, query: {}, method: request.method, statusCode: response.status, userAgent, referer: null, country: request.cf?.country || null, requestId: request.headers.get("cf-ray") || crypto.randomUUID(), timestamp: new Date().toISOString(), }), }).catch(() => {})) } return response }, } ``` 3. **Route the custom domain**: Follow Framer’s Cloudflare proxy guide to create the dummy proxied DNS record, bind the Worker route for *example.com/*, and set the canonical URL in Framer. 4. **Activate and verify**: Activate the Worker, verify normal pages and assets still load from Framer, then send an AI crawler request and confirm it appears in Virent. Check Framer's [current documentation](https://www.framer.com/help/articles/how-to-proxy-with-cloudflare/) if its screens differ from these steps. ## Verify Send a [test crawler request](/docs/analytics/ai-crawlers#verify) to your site. The setup dialog in Virent shows "Virent is receiving AI crawler traffic" once the first request arrives. --- # Capture AI crawlers on a Webflow site. > Connect Webflow to Virent AI Crawler Analytics. Use Webflow's supported Cloudflare Orange-to-Orange path, then attach an AI crawler Worker. Canonical: https://virent.app/docs/integrations/webflow Last updated: 2026-10-19 Use Webflow's supported Cloudflare Orange-to-Orange path, then attach an AI crawler Worker. Webflow has no request logs or server code. Put the site behind Cloudflare with Webflow's supported Orange-to-Orange setup, then a Cloudflare Worker reports AI crawlers. Virent only reads requests; it never changes your Webflow site. You need your site ID and server secret from **Settings → Connection** (see [Hosting integrations](/docs/integrations/overview#before-you-start)). In the dashboard, **Connect analytics → Hosting integrations → Webflow** shows these steps with your site ID, domain and secret filled in. Below, replace ``, `` and `example.com` with your own values. ### Set up with your coding agent Paste this prompt into Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own. ```text Configure Webflow so example.com sends reliable AI crawler request telemetry to Virent. Site ID: Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value. Use the current provider documentation: https://help.webflow.com/hc/en-us/articles/45039458051347-Using-Cloudflare-Orange-to-Orange-O2O-with-Webflow Steps: 1. Confirm Orange-to-Orange eligibility: Confirm the Webflow site is on migrated infrastructure and complete Webflow domain verification before enabling Cloudflare Orange-to-Orange. Do not proxy a legacy Webflow site: it can produce TLS 525 errors. 2. Enable the supported Webflow proxy: Follow Webflow’s Orange-to-Orange guide, point the proxied CNAME at cdn.webflow.com, and confirm the custom domain still resolves and serves the published site. 3. Attach AI crawler tracking: Create a Worker with this code, add VIRENT_INGEST_SECRET as a Worker secret, and bind it to the Webflow hostname after Orange-to-Orange is healthy. const SITE_ID = "" const INGEST = "https://virent.app/v1/ingest/bot" // Send eligible requests for classification by Virent. const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/i export default { async fetch(request, env, ctx) { const response = await fetch(request) ctx.waitUntil(report(request, response, env.VIRENT_INGEST_SECRET).catch(() => {})) return response }, } async function report(request, response, secret) { if (request.method !== "GET") return const url = new URL(request.url) const userAgent = request.headers.get("user-agent") || "" if (ASSET.test(url.pathname)) return const cf = request.cf || {} await fetch(INGEST, { method: "POST", headers: { "content-type": "application/json", "x-api-key": secret, }, body: JSON.stringify({ siteId: SITE_ID, url: url.origin + url.pathname, host: url.host, path: url.pathname, query: {}, method: request.method, statusCode: response.status, userAgent, accept: request.headers.get("accept"), acceptLanguage: request.headers.get("accept-language"), referer: null, country: cf.country || null, requestId: request.headers.get("cf-ray") || crypto.randomUUID(), timestamp: new Date().toISOString(), }), }) } 4. Activate and verify: Activate the Worker, verify Webflow pages and assets, then request https://example.com/ as an AI crawler and confirm it appears in Virent. Keep the secret server-side, preserve 100% request coverage where the provider supports sampling, and verify both normal site delivery and a crawler request after activation. ``` ## Steps 1. **Confirm Orange-to-Orange eligibility**: Confirm the Webflow site is on migrated infrastructure and complete Webflow domain verification before enabling Cloudflare Orange-to-Orange. Do not proxy a legacy Webflow site: it can produce TLS 525 errors. 2. **Enable the supported Webflow proxy**: Follow Webflow’s Orange-to-Orange guide, point the proxied CNAME at cdn.webflow.com, and confirm the custom domain still resolves and serves the published site. 3. **Attach AI crawler tracking**: Create a Worker with this code, add VIRENT_INGEST_SECRET as a Worker secret, and bind it to the Webflow hostname after Orange-to-Orange is healthy. ```javascript const SITE_ID = "" const INGEST = "https://virent.app/v1/ingest/bot" // Send eligible requests for classification by Virent. const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/i export default { async fetch(request, env, ctx) { const response = await fetch(request) ctx.waitUntil(report(request, response, env.VIRENT_INGEST_SECRET).catch(() => {})) return response }, } async function report(request, response, secret) { if (request.method !== "GET") return const url = new URL(request.url) const userAgent = request.headers.get("user-agent") || "" if (ASSET.test(url.pathname)) return const cf = request.cf || {} await fetch(INGEST, { method: "POST", headers: { "content-type": "application/json", "x-api-key": secret, }, body: JSON.stringify({ siteId: SITE_ID, url: url.origin + url.pathname, host: url.host, path: url.pathname, query: {}, method: request.method, statusCode: response.status, userAgent, accept: request.headers.get("accept"), acceptLanguage: request.headers.get("accept-language"), referer: null, country: cf.country || null, requestId: request.headers.get("cf-ray") || crypto.randomUUID(), timestamp: new Date().toISOString(), }), }) } ``` 4. **Activate and verify**: Activate the Worker, verify Webflow pages and assets, then request https://example.com/ as an AI crawler and confirm it appears in Virent. Check Webflow's [current documentation](https://help.webflow.com/hc/en-us/articles/45039458051347-Using-Cloudflare-Orange-to-Orange-O2O-with-Webflow) if its screens differ from these steps. ## Verify Send a [test crawler request](/docs/analytics/ai-crawlers#verify) to your site. The setup dialog in Virent shows "Virent is receiving AI crawler traffic" once the first request arrives. --- # Supported runtimes and coverage limits > What each Virent installation observes on browser-only sites, Next.js, Node.js servers and edge runtimes, and the collection controls that apply. Canonical: https://virent.app/docs/installation/runtimes-and-coverage Last updated: 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](/docs#installation) give copy-paste steps. This page states what each setup can and cannot observe. ## Recipes by runtime | Runtime | Install | Observes | Does not observe | |---|---|---|---| | Browser-only or static site | Hosted script (`/js/script.js`) or `@virent.app/sdk/browser` | Pageviews, custom events, referrers and campaign attribution, identity links, goals | Crawler 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 `createVirentAnalyticsProxy` | Browser events and crawler requests that reach the proxy | Final 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 SSR | Browser 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 process | Requests 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 isolates | Browser script plus verified provider logs for crawlers | Browser events; crawler requests as reported by the provider log integration | The Node.js crawler adapter is not an edge adapter. A crawler report from an edge runtime marks the crawler channel `unsupported`. | [Hosting integrations](/docs/integrations/overview) (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: /; runtime=`. 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. --- # Go from sign-up to your first AI answers. > Set up a Virent workspace end to end, from choosing a plan to your first monitored AI answers, analytics install and verification. Canonical: https://virent.app/docs/get-started/quickstart Last updated: 2026-10-19 Onboarding takes you through eight short steps. Visibility starts on its own after the Prompts step; installing Analytics is optional and never blocks the dashboard. ## Before you start - A brand to monitor: a company, a person or creator, a local business or anything else. A website is optional for Visibility and required for Analytics and Content Agent. - A plan. Virent has no free plan or trial: you choose a plan before any AI work runs. See [Plans and billing](/docs/workspace/plans-and-billing). - For Analytics only: access to the website's code, hosting or CMS, or a developer who has it. ## The eight onboarding steps 1. Profile: Your name, the workspace name (which sets the workspace URL) and how you heard about Virent. 2. Plan: Choose a plan in the embedded checkout, in USD or BRL, billed monthly or annually. The page waits until the plan is active, then moves on. 3. Brand: Enter the website URL. Virent reads the homepage to prepare the brand profile and find adjacent brands. No website? Choose "I don't have a website", then give the brand name, what kind of brand it is and, optionally, its profiles. 4. Review: Check the profile Virent drafted (name, other names, what you do, audience) and correct anything wrong. Without a website you fill in the same profile yourself. 5. Competitors: Confirm or dismiss each suggested competitor, or add one by name or domain. 6. Prompts: Review the suggested prompts (the questions buyers ask AI assistants), edit or dismiss them, and confirm the ones to track. Confirming starts daily monitoring. 7. Install: Connect Human Analytics and AI Crawler Analytics, or skip this step and return later. Brands without a website have nothing to install. 8. Launch: Open the dashboard. > **Your first answers arrive with the next daily run** > > Prompts run once a day. Until the first run finishes, the Overview shows "Your first AI answers are on the way". You can run a single prompt immediately from Prompt Monitoring; each answer costs one AI credit. ## Connect Analytics Analytics has two independent collection paths. Install the one that answers your question, or both. ### People on your site A site-wide browser script with the publishable key (`vha_pk_…`). Pageviews, sessions, referrers, campaigns, events, goals and funnels. [Human Analytics](/docs/analytics/human-analytics) ### AI crawlers on your site Server, edge or log-based capture with the server secret (`vha_sk_…`). Crawler requests, pages, response status and crawl rules. [AI Crawler Analytics](/docs/analytics/ai-crawlers) The fastest path is the dashboard: open **Connect analytics** in the Analytics header (or the Install step) and choose **Open in Claude Code**, **Open in Codex** or **Copy for Cursor** and other agents. The agent detects your framework. The prompt includes your publishable key and site ID; a copied prompt also includes the server secret if you used **Rotate + reveal** first, otherwise the agent asks you for it. Each [framework guide](/docs#installation) has the same prompt without keys. ## Verify each path ### Visibility Open Prompt Monitoring after the first daily run. Each prompt shows one answer per engine. Open an answer to see the full text, the brands it names and the sources it cites. ### Human Analytics Load a page of your site (not localhost), then refresh the connection status. It moves from "Waiting for first event" to "Receiving events". ### AI Crawler Analytics Run `curl -A "GPTBot" https://your-domain.com/` and refresh the connection status. A controlled user agent tests the integration; it does not prove a real crawler visited. ### Analytics in the dashboard A failed status check shows "Health unknown", never "Not installed". Check again before reinstalling anything. ## What to do next - [How Virent measures](/docs/get-started/concepts) - [Prompts and answers](/docs/visibility/prompts) - [Brands and competitors](/docs/visibility/brands-and-competitors) - [Actions](/docs/actions) - [Invite your team](/docs/workspace/team-and-roles) --- # What each number in Virent is, and what it is not. > The data model behind Virent - brands, prompts, sampled AI answers, citations, crawler requests, human sessions and attribution - and the limits of each. Canonical: https://virent.app/docs/get-started/concepts Last updated: 2026-10-19 Virent keeps every metric attached to the evidence behind it. Read this page once and the rest of the dashboard will make sense. ## Three product areas, three kinds of evidence | Area | Evidence | Needs a website | Needs an install | | --- | --- | --- | --- | | Visibility | AI answers to the prompts you monitor, collected through each engine's API | No | No | | Analytics | Browser events from people, and server-side requests from AI crawlers | Yes | Yes, per collection path | | Content Agent | Opportunities, research, drafts, reviews and publications for your articles | Yes | GitHub access to publish | Each path is independent. A site can run Visibility alone, add Human Analytics for traffic, and add AI Crawler Analytics later. ## Workspace, brand and website ### Workspace Your team's account: members, plan, billing and everything monitored. Its URL is `virent.app/`. ### Brand What Visibility monitors: a company, a person or creator, a local business or anything else. A brand has a name, other names it goes by ("Also known as") and sources it owns. ### Website The domain of a brand, when it has one. Analytics, crawler data and Content Agent belong to a website and need one. A brand without a website is tracked by name. ### Competitors Other brands you monitor in the same answers, so mentions and citations have something to compare against. ## Visibility terms ### Prompt A question people ask AI assistants, such as "best invoicing tool for freelancers". Tracked prompts run once a day on every enabled engine. ### Answer One engine's reply to one prompt on one day. Answers are sampled observations: the same question can get a different answer tomorrow, or for another person. ### Mention An answer names the brand or one of its other names. Mention rate is the share of answers that name the brand. ### Citation An answer links to a source. A citation counts for your brand when it points to your website or a source you own, such as your LinkedIn or YouTube profile. ### Share of voice Your mentions as a share of all mentions of you and your competitors in the same answers. ### Position Where the brand appears in an answer, when an answer has an observable order (a list, for example). Many answers have none. Answers come from each engine's API with a model Virent selects, not from the consumer apps people use. The provider and model are shown with every answer. ## Analytics terms ### Pageview, session and visitor A session ends after 30 minutes without activity. Visitors are visitor-days: each browser counts once per day. The browser script keeps its IDs in the site's own storage and sets no cookies. ### Event, goal and funnel Events are actions you send with the SDK. A goal is a named conversion. A funnel is an ordered list of pageviews, events or goals. ### AI referral A visit that arrives from an AI assistant, such as chatgpt.com or perplexity.ai, or with a matching UTM source. ### Crawler request A request from an AI crawler to your site, captured on the server. It is a crawl, not a citation and not a person. ## How confident a conclusion is Virent keeps signals that are directly linked separate from signals that only line up in time. A page that was crawled, then cited, then visited is a connected story; it is not proof that one caused the other. The same applies to articles published with Content Agent: changes after publication are associations. ## What Virent does not claim - It does not measure real AI search volume or every conversation people have with an assistant. - It does not guarantee mentions, citations, crawls or referral traffic. - A training crawl does not establish that a page was used for training. - Over-limit usage never drops data; see [Plans and billing](/docs/workspace/plans-and-billing). --- # Hand Virent's docs and setup to your AI agent. > Give Claude, ChatGPT, Cursor, Codex and other AI agents Virent's documentation as Markdown, with llms.txt, per-page .md URLs and ready-made install prompts. Canonical: https://virent.app/docs/get-started/ai-agents Last updated: 2026-10-27 Every page is available as Markdown, the whole documentation fits in one file, and the setup tasks come with prompts written for coding agents. ## Machine-readable site | URL | What it returns | | --- | --- | | [`/llms.txt`](/llms.txt) | A short index of Virent's pages and docs, in the llms.txt format | | [`/llms-full.txt`](/llms-full.txt) | Every public page as Markdown, in one file: product pages, documentation, legal documents | | `/.md` | One page as Markdown, for example [`/pricing.md`](/pricing.md), [`/index.md`](/index.md) or [`/docs/installation/nextjs.md`](/docs/installation/nextjs.md) | | [`/api/md/_catalog`](/api/md/_catalog) | A JSON list of every page with its HTML and Markdown URL | | [`/ai.txt`](/ai.txt) | How AI systems may use the site: permissions, restrictions, attribution and scope | | [`/sitemap.md`](/sitemap.md) | A categorized map of public pages | | [`/openapi.json`](/openapi.json) | The OpenAPI 3.1 specification of the public HTTP API | | [`/.well-known/api-catalog`](/.well-known/api-catalog) | An RFC 9727 API catalog that links the OpenAPI specification and the API reference | Every public page also returns its Markdown at its own URL when the request sends `Accept: text/markdown`, and its HTML `` names the Markdown version in a ``. Markdown responses are `noindex` and point back to the HTML page as canonical, so give an agent the `.md` URL of the page it needs rather than the whole site: it is smaller and has no navigation around the content. ## On every page Use **Copy page** at the top of any docs page to copy it as Markdown. Its menu also opens the page as Markdown, copies its link, and opens ChatGPT, Claude or Perplexity with the page ready to ask about. ## Install with a coding agent The dashboard writes the best install prompt, because it already contains your site ID and publishable key. A copied prompt also includes the server secret if you used **Rotate + reveal** first; otherwise the agent asks you for it. 1. Open Connect analytics: In the Analytics header, or in the Install step of onboarding. 2. Send the prompt: Open it in Claude Code or Codex, or copy it for Cursor, Antigravity, Windsurf, Gemini CLI, OpenCode, Continue, Zed or VS Code. Without dashboard access, use the prompt at the top of each [framework guide](/docs#installation). It holds no keys, so the agent asks you for them. > **Keep the server secret away from chats** > > The publishable key (`vha_pk_…`) is safe in browser code and prompts. The server secret (`vha_sk_…`) belongs only in your server's environment variables. Paste it into a local coding agent that writes it to an environment file, never into a public chat or a committed file. ## Prompts for other tasks ### Check an existing install Ask your coding agent to review a Virent installation against the guide. ```text Review how this project installs Virent analytics and report problems; do not change code yet. Read the Virent guide for this project's framework at https://virent.app/docs/installation/.md (nextjs, react, vue, nuxt, astro, sveltekit, express, laravel or wordpress). Check: - The browser script (or @virent.app/sdk/browser) loads on every page from the root layout or global template, with a publishable key that starts with vha_pk_. - No server secret (vha_sk_) appears in client code, public environment variables (NEXT_PUBLIC_, VITE_, PUBLIC_) or committed files. - Crawler capture runs on the server or edge before any page renders, and excludes API routes, static assets, images, favicons, robots.txt and sitemaps. - A Content-Security-Policy, if present, allows https://app.virent.app in script-src and connect-src, and https://virent.app in connect-src when @virent.app/sdk runs without an endpoint option. - @virent.app/sdk, if used, is version ^0.3.0. List each finding with the file, the problem and the fix from the guide. ``` ### Ask about Virent Paste into Claude, ChatGPT or another assistant before asking product questions. ```text Read https://virent.app/llms-full.txt. It is the complete Virent documentation. Answer my questions about Virent using only that documentation. Quote the page URL you used. If the documentation does not cover something, say so instead of guessing. ``` ## Rules agents should follow - Use only the interfaces documented here and in [`/openapi.json`](/openapi.json). Internal `/api/*` routes and `/v1/*` routes missing from the specification are not a public contract. - Pin `@virent.app/sdk` to `^0.3.0`; the released version is 0.3.1. - Never invent a site ID or key, and never use a masked preview such as `vha_sk_••••` as a real value. - Treat answers as sampled observations and crawler requests as crawls, not citations. --- # People and AI crawlers on your site, in one view. > How the Virent Analytics dashboard works - human traffic and AI crawler requests side by side, date ranges, page details, data health and plan limits. Canonical: https://virent.app/docs/analytics/overview Last updated: 2026-10-19 Analytics puts human traffic and AI crawler activity side by side, so you can see which pages AI crawlers read and which pages people visit, from AI assistants and everywhere else. ## What you need Analytics needs a website and at least one collection path: | Path | Install | What it adds | | --- | --- | --- | | [Human Analytics](/docs/analytics/human-analytics) | Browser script or SDK, publishable key | Pageviews, visitors, sessions, sources, AI referrals, events, goals, funnels | | [AI Crawler Analytics](/docs/analytics/ai-crawlers) | Server, edge or log integration, server secret | AI crawler requests, crawled pages, response status, crawl rules | The connection control in the header shows one combined state for both paths; it reads as connected only when both receive events. **Connect analytics** opens the install dialog; **Health unknown** means the status check failed, not that the install is missing. ## The Analytics page ### Key numbers Pageviews, visitors, AI crawler requests and conversions for the selected range. ### People and AI crawlers One chart with human traffic and crawler requests over time, so a change in one can be read against the other. ### Pages Two tables side by side: **Visitors** (views and visitors per page) and **AI crawlers** (providers and requests per page). Select a page for its browser activity or its AI crawler requests. ### Sources Referrers, UTM campaigns and AI referrals: visits that arrive from ChatGPT, Claude, Perplexity, Gemini, Copilot and other assistants. ### Audience Countries, devices, browsers and operating systems. ### Conversions Goals and funnels you define. See [Human Analytics](/docs/analytics/human-analytics#goals-and-funnels). ### Data health and crawler diagnostics Crawler health, response status, robots and crawl rules, pages with errors or blocks, and recent crawler requests. ## Website and dates - Website: switch between the websites in the workspace. - Date range: last 7, 30 (default), 60 or 90 days, or a custom range. The range lives in the URL, so a link shows the same view. - Timezone: each website has its own; days and charts follow it. Change it under data health. A range that ends in the future is marked incomplete. ## Usage and limits Your plan includes a monthly number of human events and AI crawler visits. Only AI crawler visits are stored and metered; other bots are dropped when they arrive. Going over never drops data: 1. Near the limit: A notice warns you before you reach it. 2. Over for one month: Data is still collected and dashboards stay open. 3. Over two months in a row: Data is still collected, and dashboards are limited until you upgrade. See [Plans and billing](/docs/workspace/plans-and-billing) for each plan's limits. --- # Measure the people who visit, including those sent by AI. > Install and configure Virent Human Analytics - the browser script, consent and privacy controls, single-page apps, custom events, identify, goals, funnels and AI referrals. Canonical: https://virent.app/docs/analytics/human-analytics Last updated: 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](/docs#installation) shows where. ```html ``` 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](/docs/installation/first-party). ## 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: ```html ``` ```js virent("consent", "granted") // or "denied" or "pending" virent("pause") // stop collecting until resume virent("resume") virent("pageview") // send a pageview manually virent("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: ```sh pnpm add @virent.app/sdk@^0.3.0 ``` ```ts import { identify, initVirent, pageview, trackEvent, trackGoal } from "@virent.app/sdk/browser" initVirent({ writeKey: "vha_pk_..." }) // sends the first pageview await trackEvent({ name: "signup_started", properties: { plan: "growth" } }) await identify({ userId: "customer_123", traits: { plan: "growth" } }) await trackGoal({ name: "signup_completed", idempotencyKey: "order_123" }) ``` - `initVirent` sends one pageview. In a single-page app using the SDK alone, call `pageview()` on each route change. - `identify` attaches an ID you choose to the visitor. Send your own opaque ID, not an email address or other personal data. - `idempotencyKey` makes a retried goal count once. - `resetVirent()` discards the active client so you can call `initVirent` again. 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](/docs/installation/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. --- # See which AI crawlers read your site, and what they get back. > 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. Canonical: https://virent.app/docs/analytics/ai-crawlers Last updated: 2026-10-19 AI crawlers never run your page's JavaScript, so Virent captures them where the request arrives - your server, edge, CDN or hosting logs - and classifies each request by provider and purpose. ## Choose a collection method Open **Connect analytics → Hosting integrations** in the dashboard for host and CDN methods, with your site's values filled in. For your own server, use a [framework guide](/docs#installation). | Where your site runs | Method | Coverage | | --- | --- | --- | | Vercel Pro or Enterprise | [Log Drains](/docs/integrations/vercel#log-drains) (recommended) | Includes CDN-cached pages, no application code | | Vercel, any plan | [Middleware](/docs/integrations/vercel#middleware) (`proxy.ts`) | Requests that reach your app | | Cloudflare | [Workers](/docs/integrations/cloudflare#workers) | Proxied zones, without blocking responses | | Cloudflare Enterprise | [Logpush](/docs/integrations/cloudflare#logpush) (recommended) | Complete edge logs, including cached responses | | AWS | [CloudFront real-time logs](/docs/integrations/aws-cloudfront) | Edge logs | | Akamai | [DataStream 2](/docs/integrations/akamai) | Edge logs | | Netlify Enterprise | [Log Drain](/docs/integrations/netlify) | Edge logs | | Google Cloud | [Load Balancer log export](/docs/integrations/google-cloud) | Load balancer logs | | Fastly | [Log streaming](/docs/integrations/fastly) | Edge logs | | Framer or Webflow | A Cloudflare Worker in front of the site ([Framer](/docs/integrations/framer), [Webflow](/docs/integrations/webflow)) | Proxied requests | | Your own server | [Framework guide](/docs#installation) or the server SDK | Requests that reach your server | Log-based methods see cached pages that middleware never sees. Middleware cannot see the final response status. See [Runtimes and coverage](/docs/installation/runtimes-and-coverage) for the details. ## Keys Crawler capture uses the website's **site ID** and **server secret** (`vha_sk_…`), from **Settings → Connection**. The secret authenticates writes from your server: keep it in server environment variables, never in browser code. See [Keys and secrets](/docs/workspace/keys). ## Server SDK For Node.js servers outside the framework guides, use the tracker from `@virent.app/sdk/server`: ```ts import { createVirentBotTracker } from "@virent.app/sdk/server" const tracker = createVirentBotTracker({ siteId: process.env.VIRENT_SITE_ID!, writeKey: process.env.VIRENT_INGEST_SECRET!, }) // In your request handler, with a Fetch API Request: void tracker.trackRequest(request, { statusCode: 200 }) ``` Call it for page requests only: skip API routes, static assets, images, favicons, `robots.txt` and sitemaps. Pass the response status when you know it. Don't await it in the response path; it gives up after 5 seconds. The [Express guide](/docs/installation/express) shows a middleware that sends the same fields over plain HTTP. ## What is stored Only requests from AI crawlers are stored and count toward your plan. Search indexers such as Googlebot, SEO tools, scrapers, monitoring and link previews are dropped when they arrive. Before sending, the SDK strips query strings, fragments, credentials, cookies, authorization headers and request bodies. ## Crawler purposes | Purpose | Shown as | What it means | | --- | --- | --- | | `ai_training` | Model training | Collects content that may be used to train models. A crawl does not establish that the page was used. | | `ai_search` | AI search | Builds the index an AI search or answer engine retrieves from. | | `answer_engine` | User-initiated fetch | Fetches a page because a person asked an assistant something. | | `unknown` | Unclassified | An AI crawler whose purpose Virent has not classified yet. | ## AI crawlers Virent recognizes | Provider | Crawlers | | --- | --- | | OpenAI | GPTBot (training), OAI-SearchBot (search), ChatGPT-User (user fetch) | | Anthropic | ClaudeBot (training), Claude-SearchBot (search), Claude-User and Claude-Web (user fetch) | | Google | Google-CloudVertexBot (training), Google-Agent and Google-GeminiNotebook (user fetch). Google-Extended is a robots.txt token, not a crawler, so it never appears in requests. | | Perplexity | PerplexityBot and Perplexity-User (user fetch) | | Meta | meta-externalagent (training), meta-webindexer (search), meta-externalfetcher (user fetch) | | Amazon | Amazonbot (training) | | ByteDance | Bytespider (training) | | Common Crawl | CCBot (training) | | DeepSeek | DeepSeekBot (user fetch) | | DuckDuckGo | DuckAssistBot (user fetch) | | You.com | YouBot (user fetch) | Virent also classifies AI crawlers from a reviewed open registry, including Mistral, Cohere, Kimi, Exa, Tavily, Firecrawl, Phind and others. Googlebot, Applebot and PetalBot are search indexers, not AI crawlers. Classification uses the user agent. Anyone can send a crawler's user agent, so a request is evidence of a claimed crawler, not proof of identity. ## In the dashboard - Crawler requests by provider, and request activity over time. - Crawled pages, with the providers and request count for each. Select one for its request log. - Response status, robots and crawl rules, and pages that return errors or blocks. - A log of recent crawler requests. [Actions](/docs/actions) turns these into tasks, such as fixing error responses on a path or letting a blocked crawler reach your pages. ## Verify ```sh curl -A "GPTBot" https://your-domain.com/ ``` Then refresh the status in **Settings → Connection**. AI crawler tracking moves from "Waiting for first event" to "Receiving events". The test request checks your integration; it is not a real crawler visit. ## Troubleshooting ### No crawler requests arrive Check that capture runs before the page renders, covers the path you tested, and uses the full server secret rather than a masked preview. ### Static files appear as pages Tighten your matcher or route exclusions for framework internals, API routes, images, favicons, `robots.txt`, sitemaps and static file extensions. ### Fewer requests than your logs show Middleware does not see CDN-cached responses. Use a log-based method on hosts that offer one. ### The secret is masked The secret is shown only once. Use **Rotate + reveal** to issue a new one, then update every install that used the old one. --- # How AI answers talk about your brand, every day. > How Virent Visibility works - the 9 AI engines, the daily schedule, mention rate, share of voice, citations and the evidence behind every score. Canonical: https://virent.app/docs/visibility/overview Last updated: 2026-10-19 Visibility asks AI engines the questions your buyers ask, every day, and records which brands each answer names and which sources it cites. No install and no website needed. ## How it works 1. You track prompts: Questions buyers ask AI assistants, suggested during onboarding or added any time. See [Prompts and answers](/docs/visibility/prompts). 2. Virent asks every engine: Each tracked prompt runs once a day on each enabled engine. 3. Each answer is analyzed: Virent records the brands it names, their position when the answer has an order, and the sources it cites. 4. You compare: Your brand against the competitors you track, over time. See [Brands and competitors](/docs/visibility/brands-and-competitors). ## Engines Every plan includes all 9 engines, enabled by default: | Engine | Where the answer's sources come from | | --- | --- | | ChatGPT | The day's shared web search | | Claude | The day's shared web search | | Gemini | The day's shared web search | | Grok | The day's shared web search | | DeepSeek | The day's shared web search | | Meta AI | The day's shared web search | | Perplexity | Perplexity's own search | | Google AI Overviews | The AI Overview on Google's search results page | For the shared web search, Virent searches the web for each prompt once a day and gives those results to each of these engines, so they all answer from the same sources. Answers come from each provider's API (Google AI Overviews from Google's results page), not from the consumer apps people use, which can personalize answers by account, location and history. Every answer shows the provider and model that produced it. To change engines, open **Settings → Assistants**. Changes apply from the next daily run; history for a turned-off engine is kept. ## Schedule - Tracked prompts run once a day, starting at 06:00 UTC. - New prompts join the next daily run. To see an answer sooner, open the prompt and choose **Run this prompt** for one answer now: one AI credit. - Paused prompts keep their history and stop running until you resume them. ## Metrics ### Mention rate The share of answers that name your brand or one of its other names. ### Share of voice Your mentions as a share of all mentions of you and your tracked competitors. ### Visibility score Mention rate and share of voice averaged, from 0 to 100. ### Position Where your brand appears in answers that list brands in order. Shown only when an order is observable. ### Citations Sources answers link to. **Top domains** lists the cited domains, each marked You, Competitor or Other, with how many answers used them. Every number opens the answers behind it. A score with no answers behind it is shown as no data, not zero. ## Read results carefully - Answers are sampled observations for your prompts, engines and schedule. They do not represent every conversation people have with an assistant. - The same prompt can get a different answer from one day to the next. Look at trends over several days before acting. - A failed or incomplete run is shown as such. It is never counted as "not mentioned". - Visibility does not measure real AI search volume, and Virent does not guarantee mentions or citations. ## Where to find it | Page | What it shows | | --- | --- | | Overview | Visibility score, mention rate, share of voice and rankings | | Prompt Monitoring | Rankings and mention rate by brand, every prompt by engine, top domains, and each answer in full | | Tracked Brands | The competitors you track and their domains: add, suggest, edit and delete them | | Content Gaps | Questions where competitors appear and you don't | --- # Track the questions your buyers ask, and read every answer. > Add, suggest, pause and run prompts in Virent Prompt Monitoring, read each AI answer with its sources, compare answers over time and find content gaps. Canonical: https://virent.app/docs/visibility/prompts Last updated: 2026-10-19 Prompts are the questions Virent asks AI engines every day for your brand. Each answer is kept in full, with the brands it names and the sources it cites. ## Write good prompts A prompt is worth tracking when a buyer could ask it before choosing a product like yours. Good prompts read like real questions: | Intent | Example | | --- | --- | | Best tools | What is the best invoicing software for freelancers? | | Comparison | Is Brand A or Brand B better for small agencies? | | Alternatives | What are good alternatives to Brand A? | | Use case | How can a freelancer send invoices in several currencies? | | Category | Which invoicing tools support recurring billing? | Avoid your brand name in most prompts: a question that names you will mention you. Track a few branded prompts separately if you want to see what assistants say about you. ## Add prompts Open **Prompt Monitoring**: - **Add prompt** to write one. - **Suggest prompts** to get prompts drafted from your brand profile, competitors and current prompts. Review and edit each before tracking it. Your plan sets how many prompts you can track (shown as "N of M tracked prompts"). If you have more than your plan includes, for example after a downgrade, every prompt keeps running but you can't add new ones until you upgrade or pause some. ## Manage a prompt Open a prompt to see its mention rate, share of voice, position, the brands it mentions and the sources cited for it. From there: ### Run this prompt Get one fresh answer now from the prompt's default model instead of waiting for the daily run. Costs one AI credit. ### Pause monitoring Stop daily runs and keep the prompt's history. Paused prompts don't count toward your tracked-prompt limit. **Resume monitoring** starts them again. ### Delete prompt Remove the prompt from monitoring. ## Read an answer Open any answer from the prompt × model table: | Section | What it shows | | --- | --- | | Run status | Completed, Collection in progress, Collection failed or Collection cancelled. A run without a completed answer is never counted as "not mentioned". | | Brands in this answer | Your brand and competitors the answer names, in order when there is one | | Full answer | The complete text | | Answer changes | A comparison with an earlier answer from the same model and collection method | | Retrieved sources | The pages the engine had available, and which ones it cited | | Search queries | The searches behind the answer, when the engine reports them | | Collection context | Method, provider, model, search mode and how URLs were normalized | | Answer quality | Signals that the answer may be incomplete or unreliable | Compare answers only within the same model and method. A change in model or method is a different measurement, not a change in what the assistant thinks. ## Content gaps **Content Gaps** lists the questions where answers mention competitors and not you, and keywords competitors share that you don't cover. Use it to decide which page to write or improve next. With [Content Agent](/docs/content-agent/overview) enabled, gaps appear as Content Agent opportunities instead. ## Troubleshooting ### A prompt has no answers New prompts run in the next daily run, from 06:00 UTC. Use **Run this prompt** to check sooner. ### My brand is never mentioned Check the brand's other names in **Settings → Brand**: the answer may use a name Virent doesn't know yet. New names apply to new answers only. ### An answer changed overnight Open both answers and compare their sources, provider and model. Day-to-day variation is normal; act on trends. ### I can't add prompts You are at your plan's tracked-prompt limit. Pause monitoring on prompts you no longer need, or change plan. --- # Tell Virent who you are, and who you compete with. > Set up the brand Virent monitors - brand type, other names, owned profiles and pages, a website - and track competitors in AI answers. Canonical: https://virent.app/docs/visibility/brands-and-competitors Last updated: 2026-10-20 Virent recognizes your brand in answers by its name, its other names and the sources it owns. Competitors give every mention something to compare against. ## Your brand Edit it in **Settings → Brand**. ### Brand type Company, person or creator, local business, or other. The type shapes the prompts Virent suggests. ### Also known as Other names an answer may use: a short name, a former name, a product name, a handle. Each name needs at least two characters. ### Profiles and pages you own Up to 25 sources whose citations count as yours: Instagram, LinkedIn, YouTube, TikTok and X profiles, another website, or any URL prefix such as a marketplace listing. ### Website Optional for Visibility. Add one later to unlock Analytics and Content Agent. New names and sources apply to answers collected after you save them. Earlier answers are not recalculated. ## Brands without a website A creator, a local business or a new company can be monitored by name alone. Mentions come from the brand's names; citations come from the profiles and pages it owns. Analytics, crawler data and Content Agent need a website and say so instead of showing empty data. A brand without a website counts as one of your plan's brands, the same as a website. See [Plans and billing](/docs/workspace/plans-and-billing#brands). ## Competitors Open **Tracked Brands** to see the competitors you track, each with its domain or "Tracked by name". Rankings, mention rate and share of voice are on **Overview** and **Prompt Monitoring**. - **Add competitor** with a name, a domain or both. A competitor without a domain is tracked by name. - Open a competitor to edit its domain, other names and positioning. - **Suggest competitors** researches the web from your business profile and proposes competitors, each with its sources. - Select competitors to delete them. Your plan lists the number of competitors per brand: 3 on Core, 8 on Growth and 15 on Scale and Plus. ## Tips - Track the competitors buyers actually compare you with. Share of voice is only as meaningful as the set it is measured against. - Add the names people really use, including common misspellings, so mentions aren't missed. - List every owned profile. A citation of your YouTube channel or LinkedIn page is a citation of you. --- # Track each brand where your buyers search. > Set the countries, languages and time zone Virent uses to monitor AI answers and Google AI Overviews for each brand. Canonical: https://virent.app/docs/visibility/markets Last updated: 2026-10-20 A market is a country and the language buyers search in. Daily monitoring, prompt suggestions and Content Agent research use your brand's markets; dates follow its time zone. ## Set markets Choose them during onboarding, or later in **Settings → Markets**. ### Primary market The country and language every tracked prompt runs in by default, for example Brazil · Portuguese. Google AI Overviews are checked in that country, and suggested prompts are written in that language. ### Extra markets Scale and Plus track up to 3 markets per brand; Core and Growth track one. A prompt can run in any of its brand's markets, and each extra market a prompt runs in counts as one more tracked prompt. ### Time zone Days in dashboards, "today" and Content Agent dates follow it. Daily monitoring itself runs on a fixed UTC schedule. Until you confirm markets, a brand uses the United States and English. Changing markets applies to answers collected after you save; earlier answers keep the market they were collected in. --- # See which sites AI answers rely on, and how your own pages do. > Understand the sites AI answers cite for your prompts, build a reviewed outreach list, and see which of your pages are cited, crawled and visited. Canonical: https://virent.app/docs/visibility/sources-and-cited-pages Last updated: 2026-10-20 Sources shows what kind of sites the monitored answers cite. Cited pages joins your own pages' citations with AI crawler visits and the visitors AI assistants send. ## Sources **Visibility → Sources** groups every cited domain by type: your site, competitors, forums and communities, video, reviews and directories, editorial, reference and other. Switch between the overall share, each engine and the trend over time. The **outreach list** shows sites the engines cite for your prompts that feature competitors but not you, ranked by how often and on how many engines they appear. Mark each one as contacted, won or dismissed, add notes, or export it as CSV. Virent never contacts a site for you. ## Cited pages **Visibility → Cited pages** lists your own pages with: - how often monitored answers cite them, and on which engines; - AI crawler fetches and when each crawler last read the page; - visits referred by AI assistants, and conversions where you track them. Four findings sit above the table: pages cited but not crawled recently, pages crawled often but never cited, pages cited without AI referrals, and pages that get AI referrals but no tracked prompt cites. Crawler and referral data need the Virent snippet or a hosting integration. ## AI Overview and organic results **Prompt Monitoring** shows, for each tracked prompt in Google, whether the AI Overview cites you and where you rank in the organic results of the same search. Checks run once a day in your brand's primary market. --- # Turn what Virent observed into a short list of work. > How Virent Actions turns visibility, analytics and crawler evidence into prioritized tasks - action types, groups, confidence, and how to start, complete or dismiss them. Canonical: https://virent.app/docs/actions Last updated: 2026-10-19 Actions reads your Visibility, Analytics and crawler data and suggests specific tasks, each with the evidence behind it and the prompts it should move. You decide what to do. ## Where to find it Open **Actions** in the sidebar. It is on every plan and open to every role except Billing; viewers can read it but not change it. | Tab | Contains | | --- | --- | | To do | Suggested actions you haven't started | | In progress | Actions you started | | History | Done, dismissed and resolved actions. Virent marks an action Resolved when its check no longer finds the problem. | Each tab is one table, highest impact first, with the action's group, impact, evidence, due date and owner. Filter it by group: **Setup**, **Technical**, **Your pages**, **New content** or **Off-site**. ## Action types | Group | Examples | | --- | --- | | Setup | Connect AI crawler tracking, install the browser SDK, turn on prompt monitoring | | Technical | Fix error responses on a path, let a crawler reach your pages, get a page crawled again, add structured data | | Your pages | Make a page worth citing | | New content | Win a prompt, publish a page for a prompt | | Off-site | Get listed on a domain that answers already cite | ## Work an action Open an action to see: - **What to do**: the task, in concrete steps. - **Prompts it should move**: the tracked prompts the action is meant to improve. - **Effect**: what changed after you completed it, measured on those prompts. - **History**: who started, completed or dismissed it, and when. Then choose **Start**, **Mark done** or **Dismiss** (with a reason). For content actions, **Start in Content Agent** (or **Update with Content Agent** for an existing page) opens the opportunity in [Content Agent](/docs/content-agent/overview) when it is enabled. ## How actions are chosen - Actions come from rules over your own data, not from a language model, and don't use AI credits. - Each action shows the evidence it rests on and a confidence level, for example "Based on 12 answers · low confidence". - Virent never acts outside your workspace: off-site actions tell you where to get listed; they don't contact anyone. - An improvement after an action is an association. Answers vary day to day, and other changes happen at the same time. --- # From an observed gap to a reviewed article, with a person in charge. > How Virent Content Agent works - brand context, opportunities, research, briefs, drafts, claim checks, review and approval, AI credits and results after publication. Canonical: https://virent.app/docs/content-agent/overview Last updated: 2026-10-19 Content Agent turns content gaps found in your AI answers into researched, fact-checked article drafts. A person reviews and approves every revision before anything is published, and GitHub is the only place it publishes. > **Early access** > > Content Agent is enabled per workspace during early access, for owners and admins. If you don't see **AI Content** in the sidebar, [contact Virent](/contact) to join. ## The workflow 1. Brand context: Describe your company once, in **Settings → Brand context**. Articles need a reviewed brand context. 2. Opportunities: Content Agent ranks gaps from your answers and Actions by priority score. 3. Research: It searches and reads sources for the opportunity, then writes a brief. 4. Draft: It writes the article from the brief, after showing you the credit cost. 5. Review: Your team edits the draft, checks each claim against its sources and approves the exact revision. 6. Publish: Virent opens a pull request in your GitHub repository. See [GitHub publishing](/docs/content-agent/github-publishing). 7. Results: The article is linked to the prompts it targets, so you can follow them after it goes live. ## Brand context Brand context is what every draft is written from: company facts, audiences, positioning, how you differ from competitors, voice, sources, claims you can make, and writing samples. **Use confirmed onboarding** fills a first version from your onboarding answers. Each save is a new version; reviewing it is a separate step, so drafts never use a version nobody checked. ## Opportunities Open **AI Content → Opportunities**. Each opportunity shows its priority score, the prompts and answers behind it, matching pages you already have, and a suggested target: a new page, or an update to an existing one. **From Actions** lists opportunities handed over from [Actions](/docs/actions). **Assess a prompt** checks any tracked prompt for an opportunity. ## Articles Start from an opportunity or a brief with **New article**. When the brief targets an existing page, the draft starts from that live page, imported as Markdown. Importing respects `robots.txt` and never changes the live page. The article editor has these panels: | Panel | What you do there | | --- | --- | | Brief | Read and adjust the research brief the draft follows | | Claims | Check each factual claim against its sources | | Review | Comment, request changes, submit for review and approve | | SEO | Search demand, search results and AI Overview observations, and a live page check | | Publish | Preview the exact files and submit the approved revision | | Results | The prompts linked to the article and what changed after publication | | History | Every revision, review and publication | Saving warns you if someone else saved a newer version first. ## AI credits Content Agent uses AI credits, an allowance separate from your Analytics volume and daily prompt monitoring. | Item | Credits | | --- | --- | | Standard article | 40 | | Deep-research article | 160 | | Running one prompt on demand | 1 per answer | - A draft is charged only when it reaches review. Failed or cancelled drafts cost nothing. - Each draft shows its price before it starts. With no credits left, new jobs don't start; there is no overage. - Monthly credits carry over for one month. Owners, admins and Billing members can set a **Monthly spend cap** in **Settings → Billing**. - Top-ups are opt-in: 500 credits for $60 or 1,500 for $170, valid for 12 months. See [Plans and billing](/docs/workspace/plans-and-billing) for each plan's monthly credits. ## Results after publication **Results** follows the prompts linked to the article on their normal daily schedule. **Pause monitoring** on an article leaves new runs out of its comparisons; the prompts keep running on their daily schedule. A change in mentions or citations after publication is an association: answers vary, and other things change at the same time. Content Agent never proves that an article caused traffic or revenue. ## What Content Agent never does - Publish, change or revert anything on your site without a person approving that exact revision. - Publish anywhere other than GitHub. - Contact anyone outside your workspace. --- # Publish approved articles to your repository through GitHub. > Connect a GitHub repository to Virent Content Agent - repository, branch, folders, file format, frontmatter, pull requests, approval, live checks and reverts. Canonical: https://virent.app/docs/content-agent/github-publishing Last updated: 2026-10-19 Content Agent writes approved articles as Markdown or MDX files in your site's GitHub repository. Your normal review, merge and deploy process stays in charge. > **Early access** > > GitHub publishing is set up with Virent per workspace during Content Agent early access. GitHub is the only publishing destination. ## Connect a repository Open **Settings → Publishing**. Owners and admins see four steps: 1. Choose the repository: The GitHub owner and repository your site is built from. 2. Add GitHub App access: Enter the GitHub App and installation IDs for that repository. 3. Authorize GitHub: Sign in to GitHub to confirm you can push to the repository. 4. Check the repository: Virent confirms the branch and folders exist and that it has the access it needs. ## Settings | Setting | Meaning | | --- | --- | | Base branch | The branch your site deploys from, such as `main` | | Articles folder | Where article files are written, such as `content/blog` | | Images folder | Where approved images are written | | File format | Markdown, or restricted MDX | | Frontmatter | Which frontmatter fields hold the title, slug, description and canonical URL | | How to publish | **Open a pull request**, or **Commit directly (needs approval)** | Use pull requests unless your team has a reason not to: your usual checks and reviewers see every change. ## Publish an article 1. Approve: A reviewer approves the exact revision. Any later edit needs a new approval. 2. Preview: The **Publish** panel shows the files that will change. 3. Submit: Virent opens a pull request with those files. The article shows "Pull request opened". 4. Merge and deploy: Your team merges it through your usual process. Virent tracks whether it was merged or closed and the deployment status. 5. Live check: Virent loads the live page and confirms its canonical URL, the approved title, and most of a sample of passages from the approved text. A pull request is not a publication until you merge it. Virent never merges for you. ## Revert Under **Undo this publication**, review the files, choose **Approve revert**, then **Open revert pull request**. Virent never force-pushes and never merges it. ## Troubleshooting ### The repository check fails Confirm the base branch and folders exist, and that the GitHub App is installed on this repository with access to contents and pull requests. ### The live check fails Check that the pull request was merged and deployed, and that the page URL matches the slug and canonical URL in the frontmatter mapping. ### The article needs another change after approval Edit it, then approve the new revision. Only the approved revision can be published. --- # Invite your team with the access each person needs. > Invite members to a Virent workspace and choose roles - owner, admin, developer, marketer, analyst, member, viewer and billing - with seats and invitations explained. Canonical: https://virent.app/docs/workspace/team-and-roles Last updated: 2026-10-19 Every member has one role in the workspace. Owners and admins invite people and choose their roles in Settings → Members. ## Invite a member 1. Open Settings → Members: Only owners and admins can invite. 2. Enter an email and a role: The person gets an email invitation. 3. They accept: They sign in, or sign up with the invited email, and join the workspace. If they are signed in with another email, they sign out first. Your plan includes a number of seats, shown as "N of M seats used". Pending invitations use a seat until they are accepted or expire. ## Roles | Role | Can | | --- | --- | | Owner | Everything an admin can do; every workspace has one owner | | Admin | Invite members, and manage billing, keys, websites, brands, prompts, Content Agent | | Developer | Install and manage keys and websites, manage and run prompts, read most dashboards (not Reports) | | Marketer | Manage brands, competitors and prompts, run prompts, read the dashboards | | Analyst | Read every dashboard, compare and export citations, complete actions | | Member | Same as Analyst | | Viewer | Read dashboards, prompts and actions, without changing anything | | Billing | Manage the plan, billing and invoices; no product data | Content Agent is available to owners and admins. --- # Two keys per website, for two different places. > Virent's publishable browser key and server secret - where each belongs, how to reveal and rotate the secret, and how to keep it out of client code. Canonical: https://virent.app/docs/workspace/keys Last updated: 2026-10-19 The publishable key goes in browser code. The server secret goes only in your server's environment. Both are in Settings → Connection. ## The two keys | | Publishable key | Server secret | | --- | --- | --- | | Prefix | `vha_pk_` | `vha_sk_` | | Used by | Browser script and browser SDK | Server, edge, middleware and log integrations (hosting integrations call it the **Connection secret**) | | Where it lives | Your page's HTML or browser bundle | Server environment variables or your host's secret store | | Can be public | Yes; it only accepts events from your website's allowed origins | Never | | Shown in the dashboard | In the copyable install snippets and prompt | Once, after you rotate it (**Rotate + reveal**) | Each website also has a **site ID** (`VIRENT_SITE_ID`), used with the server secret. It is not a secret. ## Keep the server secret safe - Store it as `VIRENT_INGEST_SECRET` in server environment variables. - Never put it in variables your framework exposes to the browser, such as `NEXT_PUBLIC_`, `VITE_`, `PUBLIC_` or `NUXT_PUBLIC_`. - Never commit it, paste it into a public chat, or include it in a screenshot or support request. - Never use the masked preview (`vha_sk_••••`) as the value. It is not the secret. ## Rotate the server secret Open **Settings → Connection** and choose **Rotate + reveal** next to **Server secret**. 1. Copy the new secret immediately: Secrets are shown once after rotation. 2. Update every install: Replace `VIRENT_INGEST_SECRET` wherever the old secret was used, and redeploy. 3. Verify: Refresh the installation status and confirm crawler events still arrive. Rotating stops the old secret at once. Installs that still use it stop sending crawler data until you update them. ## If a secret leaks Rotate it right away, update your installs, then remove the old value from wherever it leaked (repository history, logs, shared documents). Rotation is what makes the leaked value useless. --- # What each plan includes, and what happens at the limits. > Virent plan limits for tracked prompts, brands, seats, AI credits, human events and AI crawler visits, plus extra brands, billing, plan changes and over-limit behavior. Canonical: https://virent.app/docs/workspace/plans-and-billing Last updated: 2026-10-20 Every plan includes all 9 AI engines (ChatGPT, Google AI Overviews, Google AI Mode, Perplexity, Gemini, Claude, Grok, DeepSeek and Meta AI). Plans differ in how much you monitor and collect. You choose a plan before setup starts. ## Plans | | Business Core | Business Growth | Business Scale | Business Plus | | --- | --- | --- | --- | --- | | Price per month (USD) | $99 | $249 | $599 | $999 | | Tracked prompts, refreshed daily | 25 | 60 | 150 | 250 | | AI engines | 8 | 8 | 8 | 8 | | Brands | 1 | 2 | 5 | 10 | | Extra brand, per month | Not available | $49 | $49 | $49 | | Competitors per brand | 3 | 8 | 15 | 15 | | Seats | 2 | 5 | 10 | 25 | | AI credits per month | 150 | 500 | 1,200 | 2,000 | | Human events per month | 100k | 500k | 2M | 10M | | AI crawler visits per month | 50k | 250k | 1M | 5M | Prices are also available in BRL. Annual billing costs 10 months, so 2 months are free. Need more seats? Upgrade your plan or [contact us](/contact). Current prices are on the [pricing page](/pricing). ## Brands A brand is one website you monitor, including its subdomains, or a brand tracked by name without a website. Each one counts once, whichever workspace it is in. - Tracked prompts are shared across all your brands. - Competitors are counted per brand and never use a brand. - On Growth, Scale and Plus, add **extra brands** for $49 a month each in **Settings → Billing**. An extra brand adds no prompts. Annual plans pay for extra brands yearly, at 10 months' price. - Adding extra brands charges the prorated amount for the rest of the period right away. Removing them credits the unused time on your next invoice. - On Core, upgrade to Growth for a second brand. There is no free plan or trial. You pay first, then setup and the first AI answers start. ## When you reach a limit | Limit | What happens | | --- | --- | | Human events and AI crawler visits | Data is always collected. After two months in a row over the limit, dashboards are limited until you upgrade. | | Tracked prompts | Every existing prompt keeps running daily; you can't add more until you upgrade or pause some. | | AI credits | New Content Agent jobs and on-demand runs don't start. There is no overage charge. | | Brands | Every brand keeps being monitored; you can't add another until you add an extra brand, upgrade, or remove one. | | Seats | You can't invite more people until a seat is free. Pending invitations use a seat. | Notices in the dashboard warn you before a limit is reached. ## AI credits Credits pay for Content Agent drafts and for running prompts on demand. Daily monitoring of tracked prompts does not use credits. - Standard article: 40 credits. Deep-research article: 160 credits. On-demand prompt run: 1 credit per answer. - Monthly credits carry over for one month. - Top-ups are opt-in: 500 credits for $60 or 1,500 for $170, valid for 12 months. - Owners, admins and the Billing role can set a **Monthly spend cap**. Usage alerts appear in the app at 75%, 90% and 100%. ## Manage billing Open **Settings → Billing** (owners, admins and the Billing role): - **Switch plan**. Upgrades apply immediately; downgrades apply at the end of the billing period. Extra brands move with you, and end if you move to Core. - See how many brands you use and change your **Extra brands**. - Switch to annual billing. - See this month's usage of human events and AI crawler visits. - **Buy more credits** and set the **Monthly spend cap**. - Open the billing portal for payment methods and invoices. - Cancel, or keep a subscription you scheduled to cancel. If a renewal payment fails, you keep full access for 7 days while you update the payment method. --- # Serve analytics from your own domain. > Relay the Virent browser script and events through your own domain under /_vr, with the headers Virent needs, for Next.js, nginx, Cloudflare Workers and other reverse proxies. Canonical: https://virent.app/docs/installation/first-party Last updated: 2026-10-26 Ad blockers and privacy tools block known third-party analytics hosts, which silently drops visits. Relaying the script and events through your domain recovers most of them. ## Two options | Option | Where | How Virent trusts the visitor's network | | --- | --- | --- | | Relay (recommended) | Next.js `proxy.ts`, nginx, a Cloudflare Worker or any reverse proxy | Forwarded headers, authenticated with the website's server secret | | SDK route | A Next.js route handler with `createVirentAnalyticsProxy` (`/vt/*`) | The same headers and secret, set by the SDK | Each [framework guide](/docs#installation) has a "First-party (recommended)" section with copy-paste code, and the dashboard's **Connect analytics** dialog has the same snippets under **Install manually** → **First-party (recommended)**. ## Relay contract - Relay only two paths under `/_vr` on your domain: `/_vr/js/script.js` to `https://app.virent.app/js/script.js`, and `/_vr/v1/*` to `https://app.virent.app/v1/*`. - Forward only the `accept-language`, `content-type`, `origin` and `user-agent` request headers. - Add `x-virent-forwarded-for` with the visitor's IP as your relay sees it, and `x-virent-forwarded-country` with the ISO country code when your host provides it. - Add `x-virent-proxy-key` with your website's server secret (`vha_sk_…`). Virent ignores the forwarded headers without it, and refuses a secret that belongs to another website. Keep the secret in your relay's configuration or environment, never in browser code. - Never forward cookies or authorization headers. Then load the script from your domain: ```html ``` With the browser SDK, pass `endpoint: "/_vr/v1/ingest/batch"`, `identifyEndpoint: "/_vr/v1/identify"` and `goalEndpoint: "/_vr/v1/track/goal"` to `initVirent`. SDK 0.3.1 does not derive the identify and goal URLs from a relative `endpoint`. ## Why plain rewrites are not enough Without the forwarded headers and the secret, every visit would arrive with your relay's IP and location: all visitors would look like one person in one country, and they would share one visitor's rate limit. A `rewrites()` entry in `next.config.js` or `vercel.json` can't add request headers, so on Next.js the relay is a rewrite in `proxy.ts`. ## Verify 1. Open your site: With the browser's network panel open. 2. Check the requests: `/_vr/js/script.js` loads from your domain, and pageviews post to `/_vr/v1/ingest/batch`. 3. Check the dashboard: Visits arrive with the right countries, not your server's. --- # Find the fix for the most common problems. > Fixes for missing pageviews, missing crawler requests, empty or changing AI answers, keys, limits and billing, plus answers to common Virent questions. Canonical: https://virent.app/docs/reference/troubleshooting Last updated: 2026-10-26 Start with the symptom. Each answer points to the page with the full detail. ## Analytics ### No pageviews arrive Check that `/js/script.js` loads on every page from the root layout or global template, that the publishable key is complete, and that you are not testing on localhost without `data-allow-localhost="true"`. A Content-Security-Policy must allow `https://app.virent.app` in `script-src` and `connect-src`, plus `https://virent.app` in `connect-src` if you use the SDK without an `endpoint`. See [Human Analytics](/docs/analytics/human-analytics). ### Visits are lower than in another analytics tool Ad blockers and privacy tools block third-party analytics hosts. Relay the script through your own domain: see [First-party analytics](/docs/installation/first-party). ### Client-side route changes are not counted The browser script follows client-side navigation. With the SDK alone, call `pageview()` after each route change. ### No crawler requests arrive Check that capture runs on the server or edge before the page renders, covers the path you tested, and uses the full server secret, not the masked preview. Test with `curl -A "GPTBot" https://your-domain.com/`. See [AI Crawler Analytics](/docs/analytics/ai-crawlers). ### Static files show up as crawled pages Exclude framework internals, API routes, images, favicons, `robots.txt`, sitemaps and static file extensions in your matcher or route rules. ### Events are rejected or return 429 Browser events, identify calls and goals must be dated within the last 72 hours and no more than 5 minutes ahead; others come back with `status: "rejected"` and `reason: "timestamp_out_of_range"`, and the batch response counts them in `rejected`. Crawler logs from server and provider ingest may be up to 7 days old. Each website key also has a per-minute event ceiling of 20 times the plan's average minute (at least 1,000 events a minute), on top of the per-visitor limit; past it Virent answers 429 with `Retry-After` and stores nothing, so retry after that many seconds. ### The dashboard says Health unknown Virent couldn't check the installation right now. It does not mean the install is missing; refresh the status before changing anything. ## Visibility ### A prompt has no answers yet Prompts run daily from 06:00 UTC. New prompts join the next run. Use **Run this prompt** to check sooner (one AI credit per answer). ### My brand is never mentioned Add the names answers actually use under **Settings → Brand → Also known as**, and list the profiles you own. New names apply to new answers. See [Brands and competitors](/docs/visibility/brands-and-competitors). ### An answer changed from one day to the next Answers are sampled observations and vary. Compare the two answers' sources, model and collection method in the answer drawer, and act on trends over several days. ### A run failed Failed and incomplete runs are labeled as such and never count as "not mentioned". The prompt runs again the next day. ### Why doesn't the answer match what I see in ChatGPT? Virent asks each engine through its API with a fixed setup, every day. The consumer apps personalize answers by account, history and location. See [Visibility overview](/docs/visibility/overview). ## Account, keys and billing ### I can only see a masked server secret The secret is shown once. Use **Rotate + reveal** in **Settings → Connection**, then update every install. See [Keys and secrets](/docs/workspace/keys). ### I can't add prompts, brands or members You reached a plan limit. A website and a brand without one each count as a brand. See [Plans and billing](/docs/workspace/plans-and-billing). ### We went over our monthly events Data is still collected. Dashboards are limited only after two months in a row over the limit. ### I don't see AI Content Content Agent is in early access and available to owners and admins of enabled workspaces. [Contact Virent](/contact) to join. ### Is there a free plan or trial? No. You choose a plan before setup starts, so the first AI answers can run right away. ## Data and privacy ### What does Virent collect? Only what you enable: answers to your prompts for Visibility; pageviews, sessions, sources, events and goals for Human Analytics; AI crawler request metadata for AI Crawler Analytics. ### What should we never send? Passwords, payment-card data, health data, government IDs, precise location, secrets or other sensitive personal data, in events, traits or URLs. ### Where are the legal terms? See the [Privacy Policy](/privacy), [Terms of Service](/terms), [Data Processing Addendum](/dpa) and [Security](/security). ## Still stuck? Tell us your framework, your hosting and what you expected to see. Don't include passwords, keys, server secrets or customer data. - [Contact Virent](/contact) --- # Privacy Policy > This policy explains how Virent collects, uses, discloses, and protects personal information across our websites, applications, analytics SDK, and related services. Canonical: https://virent.app/privacy Last updated: 2026-10-27 Effective October 27, 2026. ## Scope and our role This Privacy Policy applies to Virent’s websites, waitlist, applications, software development kits, APIs, support channels, and related services (collectively, the “Services”). “Virent,” “we,” “us,” and “our” refer to L Partner Corp, a Delaware corporation doing business as Virent, the provider of the Services, or another provider identified in an applicable order form or agreement. When we handle account, website, waitlist, sales, or support information for our own purposes, Virent acts as a controller, including a controlador under Brazil’s LGPD, or a business where those terms apply. When a customer uses Virent to collect or analyze information from its own websites, applications, prompts, or users, Virent generally acts as a processor, operador under the LGPD, or service provider on that customer’s instructions. The customer remains responsible for its own notices, choices, lawful basis, and instructions. ## Information we collect ### Information you provide - Account and profile details, such as name, business email, authentication details, workspace, and role. - Waitlist and business details, such as name, email, phone number, and website. - Billing and transaction details handled by us or our payment providers when paid services are available. - Communications, feedback, support requests, and any files or context you choose to provide. ### Information generated through the Services - Service and device data, including log events, browser or device type, timestamps, referring pages, and approximate network context. - Human analytics selected by a customer, such as pageviews, sessions, referral context, pseudonymous identifiers, events, and conversion goals. - Crawler analytics, such as requested URL, bot classification, user-agent, response status, timing, and pseudonymous or derived network signals. Network addresses may be processed transiently for security, rate limiting, or derivation where configured. - LLM visibility and prompt-tracking data, including prompts, model or provider, generated answers, mentions, rankings, citations, comparison results, and run history. - Content Agent data, including brand context, research queries, retrieved public-page snapshots and excerpts, search-demand and results-page observations, briefs, drafts, revisions, claim checks, approvals, and publication records. - Product usage and configuration data, including integrations, monitored domains, filters, saved views, and feature interactions. ### Information from other sources - Information a workspace administrator or teammate provides about authorized users. - Publicly available website, domain, company, and citation information needed to perform requested visibility analysis. - Information from integrations that a customer chooses to connect, subject to that integration’s settings and terms. - Repository information from GitHub repositories a customer connects through the Virent GitHub App, limited to the repositories and permissions the customer grants. - Public web pages, search results, and AI answers retrieved for visibility monitoring and content research a customer requests. ## How we use information Depending on context and applicable law, we rely on performance of a contract or pre-contractual steps, legitimate interests in operating and protecting the Services after considering necessity and individual rights, consent where required, compliance with legal or regulatory obligations, and the establishment or defense of legal claims. We do not use Customer Data to train general-purpose AI models unless the customer expressly agrees. - Provide, operate, secure, troubleshoot, and improve the Services. - Create accounts, manage workspaces, process waitlist requests, and communicate about access. - Measure human activity, classify crawler traffic, run prompt and visibility analyses, and generate customer-requested reports. - Research, draft, and review content a customer requests, publish only revisions a customer approves to the destinations it connects, and track what changed after publication. - Personalize settings, maintain service integrity, prevent abuse, enforce terms, and comply with law. - Understand feature performance and develop new functionality using aggregated, de-identified, or otherwise lawfully processed information. ## How we disclose information We disclose information only as needed for the purposes described in this policy. We do not sell personal information or share it for cross-context behavioral advertising. - Vendors and subprocessors that provide hosting, storage, security, authentication, communications, payments, analytics infrastructure, web research, search data, or AI model access under contractual safeguards. The Data Processing Addendum lists current subprocessors and the data each receives. - Workspace administrators and authorized users according to the customer’s settings. - Integration providers when a customer directs us to connect or transmit data, such as GitHub when a customer approves an article for publication to a connected repository. - Professional advisers, authorities, or other parties when reasonably necessary to comply with law, protect rights and safety, investigate abuse, or complete a corporate transaction. ## Cookies and similar technologies We may use cookies or local storage that are necessary for authentication, security, preferences, and reliable operation. We do not use the Virent website for cross-context behavioral advertising. A customer that deploys Virent analytics on its own property controls that deployment and is responsible for any consent or notice required by law. ## Retention We retain personal information only as long as reasonably necessary to provide the Services, satisfy the purposes described here, meet contractual or legal obligations, resolve disputes, and protect the Services. Retention depends on the data type, workspace settings, agreement, and whether the information can be safely deleted or de-identified. Customer Data is returned or deleted as described in the applicable agreement and Data Processing Addendum. Unless an agreement or workspace setting says otherwise, these default periods apply: - Human analytics events: 395 days. - Crawler analytics events: 90 days. - Usage records: 730 days. - Raw web pages fetched for content research: 90 days, or less where the source’s terms require. - Approved article revisions and the supporting excerpts we are permitted to keep: retained with the article until it is deleted. - Operational logs: 30 days, limited to identifiers and minimal content. - Audit and billing records: as long as contractual, legal, or accounting requirements need. ### Deletion Deletion removes data from active systems within a reasonable period. Copies in protected backups are removed as backups expire under normal cycles, so we do not promise immediate erasure from backups. Content a customer has already published to its own repository or another remote destination stays under the customer’s control; Virent does not delete or revert it. ## Security We use administrative, technical, and organizational safeguards designed for the nature and risk of the information we process. These include access controls, data minimization, encryption in transit, protected secrets, logging, and incident response practices where appropriate. No system can guarantee absolute security. Please report suspected security issues privately to our contact email and do not include secrets or unnecessary personal information. ## International data transfers Virent and its providers may process information in countries other than where it was collected. For information protected by European or UK law, we use a lawful transfer basis where required, such as an adequacy decision, the European Commission’s Standard Contractual Clauses, or the UK International Data Transfer Agreement or Addendum, together with transfer-risk assessments and supplementary measures where appropriate. For personal data transferred from Brazil, we apply the mechanisms required by the LGPD and ANPD Resolution CD/ANPD No. 19/2024. Depending on the transfer, this may include an ANPD adequacy decision, the Brazilian standard contractual clauses, approved specific contractual clauses, global corporate rules, or another mechanism expressly permitted by the LGPD. EU or foreign adequacy decisions do not by themselves authorize a Brazilian transfer. ## Your privacy rights Depending on where you live, you may have rights to confirm whether we process your information; access, correct, anonymize, block, restrict, object to, or delete it; receive a portable copy where technically and legally available; withdraw consent; obtain information about disclosures and the consequences of withholding consent; opt out of certain processing; or appeal a denied request. You may also have rights concerning solely automated decisions that produce legal or similarly significant effects. To make a request, email virent.app@gmail.com. Requests may be submitted in English or Portuguese. Describe the request and the account, workspace, or email involved. We may verify your identity and authority before acting. We will respond within the period required by applicable law. If Virent processes the information for a customer, we may direct you to that customer or assist it with the request. ## European, UK, and Swiss disclosures If the GDPR, UK GDPR, or Swiss Federal Act on Data Protection applies, you may exercise the applicable rights described above and lodge a complaint with the supervisory authority where you live, work, or believe an infringement occurred. You may withdraw consent without affecting processing that was lawful before withdrawal and object to processing based on legitimate interests. Virent is not designed to make decisions about individuals based solely on automated processing that produce legal or similarly significant effects. If a customer uses Virent output in such a process, that customer is responsible for the decision, required safeguards, human review, and notice. Where legally required, Virent will designate an EU or UK representative or data protection officer and publish the relevant details. ## Brazil disclosures If the Lei Geral de Proteção de Dados Pessoais, Law No. 13,709/2018 (LGPD), applies, Virent processes personal data in accordance with the LGPD principles of purpose, adequacy, necessity, free access, data quality, transparency, security, prevention, nondiscrimination, and accountability. Brazilian data subjects may request confirmation and access; correction; anonymization, blocking, or deletion of unnecessary, excessive, or unlawfully processed data; portability as regulated; deletion of data processed on consent, subject to legal retention; information about public and private entities with which data was shared; information about the consequences of withholding consent; consent withdrawal; review of qualifying automated decisions; and an explanation of the criteria used, subject to lawful protections for trade and industrial secrets. Virent provides virent.app@gmail.com as its channel for Brazilian data subjects and the ANPD. Where Virent is an operador for a customer, the customer is the controlador responsible for the request. You may petition the Autoridade Nacional de Proteção de Dados (ANPD) after first raising the matter with the relevant controlador, as applicable. ## Additional United States disclosures During the preceding 12 months, we may have collected the categories described above: identifiers and contact information; internet or electronic activity; commercial and account information; approximate geolocation derived from network information; professional information; and inferences related to product or visibility analytics. We collect and disclose these categories for the business purposes described in this policy. We do not sell personal information, share it for cross-context behavioral advertising, or use sensitive personal information to infer characteristics about individuals. Where applicable, authorized agents may submit requests, and eligible users may appeal a decision by replying to our response. ## Children The Services are designed for businesses and are not directed to children under 16. We do not knowingly collect personal information from children through the Services. If you believe a child has provided information, contact us so we can review and delete it where appropriate. ## Changes and contact We may update this policy to reflect changes to the Services, law, or our practices. We will post the revised policy with a new effective date and provide additional notice when required. Questions, privacy requests, security reports, and other contacts should be sent to virent.app@gmail.com. This is also Virent’s privacy contact channel for data subjects, supervisory authorities, and the ANPD. The controller’s registered office is 2140 S Dupont Hwy, Camden, DE 19934, USA. If law requires Virent to appoint and publicly identify a data protection officer, representative, or encarregado, we will update this section with that person’s or representative’s details. ## Related - [Terms of Service](https://virent.app/terms) - [Data Processing Addendum](https://virent.app/dpa) - [Contact](https://virent.app/contact): Privacy, legal and security contact paths. --- # Terms of Service > These Terms govern access to and use of Virent’s websites, applications, SDKs, APIs, analytics, and related services. Canonical: https://virent.app/terms Last updated: 2026-10-27 Effective October 27, 2026. ## Agreement to these Terms The Services are provided by L Partner Corp, a Delaware corporation doing business as Virent (“Virent,” “we,” or “us”). By accessing or using the Services, you agree to these Terms of Service (the “Terms”) on behalf of yourself or the organization you represent (“Customer” or “you”). If you accept for an organization, you represent that you have authority to bind it. If you do not agree, do not use the Services. An order form, statement of work, Data Processing Addendum, or other written agreement signed or accepted by Virent and Customer may add to these Terms. If there is a conflict, the more specific written agreement controls for that conflict. ## Eligibility and accounts - You must be at least 18 and legally able to enter this agreement. - You must provide accurate account information and keep it current. - You are responsible for account credentials, authorized users, workspace permissions, and activity under your account. - You must promptly notify us of suspected unauthorized access. ## The Services Virent provides telemetry-first analytics for human website activity, AI and search crawler activity, LLM visibility, prompts, answers, citations, competitors, and related reporting. Features may vary by plan, configuration, provider availability, or launch stage. Early-access, beta, preview, or experimental features may change, be suspended, or be discontinued. They may be less reliable than generally available features and should not be used where failure could cause material harm. ## Orders, fees, and taxes Paid plans, usage limits, fees, billing cycles, and renewal terms will be stated at purchase or in an order form. Unless stated otherwise, fees are non-refundable except where law requires, and Customer is responsible for applicable taxes other than taxes on Virent’s income. We may change future pricing with advance notice; changes do not alter a current committed term unless agreed. ## Customer Data and instructions “Customer Data” means data, content, prompts, domains, events, configurations, and other material submitted to or collected through the Services for Customer. Customer retains its rights in Customer Data and grants Virent a limited, worldwide license to host, copy, process, transmit, and display it only as needed to provide, secure, support, and improve the Services as permitted by these Terms. Customer is responsible for the legality, accuracy, quality, and collection of Customer Data; establishing and documenting a lawful basis; providing required notices; obtaining consent where required, including for non-essential analytics storage or tracking; honoring user choices and data-subject rights; and configuring the Services appropriately under laws such as the GDPR, UK GDPR, LGPD, and applicable electronic communications and consumer laws. Customer must not submit secrets, payment-card data, health data, government identifiers, precise location, or other sensitive personal information unless Virent has expressly agreed in writing to process it. ## Telemetry, domains, and integrations - Customer may monitor only domains, properties, data, and accounts it owns or is authorized to analyze. - Customer controls which SDK, middleware, event, identity, prompt, provider, and integration features it enables. - Third-party integrations and model providers are governed by their own terms and availability. - Customer must not use the Services to bypass access controls, robots directives, provider restrictions, or applicable law. ## Acceptable use You may not use the Services to: - Violate law, third-party rights, privacy, or contractual restrictions. - Access or monitor systems, data, or domains without authorization. - Send malware, harmful code, spam, or content intended to disrupt or deceive. - Probe, scan, overload, reverse engineer, copy, or circumvent the Services except where law expressly permits. - Use automated means that materially burden the Services outside documented interfaces or agreed limits. - Build a competing service from non-public elements of the Services or resell access unless Virent agrees in writing. ## Ownership and feedback Virent and its licensors own the Services, software, designs, documentation, trademarks, and related intellectual property, excluding Customer Data. Subject to these Terms, Virent grants Customer a limited, non-exclusive, non-transferable, revocable right to use the Services during the applicable term for its internal business purposes. If you provide feedback, you grant Virent a perpetual, irrevocable, worldwide, royalty-free right to use it without restriction or attribution. This does not transfer ownership of Customer Data. ## Confidentiality Each party may receive non-public information that a reasonable person would understand to be confidential. The receiving party will use it only to perform under the agreement, protect it with reasonable care, and disclose it only to personnel and providers with a need to know and confidentiality duties. These obligations do not apply to information lawfully known without restriction, independently developed, publicly available through no breach, or rightfully received from another source. A legally required disclosure may be made after notice where legally permitted. ## AI-generated and third-party results Answers, citations, classifications, recommendations, and other automated outputs may be incomplete, inaccurate, delayed, or changed by third-party providers. Virent does not control third-party model behavior or guarantee that any crawler, model, provider, or user will access, cite, rank, or refer to Customer. You must review outputs and evidence before making legal, financial, security, or other high-impact decisions. ## Privacy and security Our Privacy Policy describes our handling of personal information. The Data Processing Addendum applies when Virent processes personal data on Customer’s behalf and is incorporated where required. Both parties will maintain safeguards appropriate to their responsibilities. No internet service is completely secure, and Customer remains responsible for its systems, credentials, configurations, and backups. ## Suspension and termination We may suspend access when reasonably necessary to prevent harm, address a security risk, comply with law, enforce these Terms, or respond to overdue fees, and will use reasonable efforts to limit scope and provide notice where practical. Either party may terminate as allowed by an order form or if the other party materially breaches and does not cure within 30 days after notice. Virent may terminate free or preview access on reasonable notice. After termination, Customer’s right to use the Services ends. Customer should export needed data before termination. We will delete or return Customer Data as required by the applicable agreement, subject to legal retention, backup, and security obligations. Provisions that by their nature should survive will survive. ## Disclaimers TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SERVICES ARE PROVIDED “AS IS” AND “AS AVAILABLE.” VIRENT DISCLAIMS ALL EXPRESS, IMPLIED, AND STATUTORY WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, AND ANY WARRANTY THAT THE SERVICES WILL BE UNINTERRUPTED, ERROR-FREE, OR PRODUCE A PARTICULAR BUSINESS, SEARCH, OR AI-VISIBILITY RESULT. NOTHING IN THESE TERMS EXCLUDES A WARRANTY THAT CANNOT LAWFULLY BE EXCLUDED. ## Limitation of liability TO THE MAXIMUM EXTENT PERMITTED BY LAW, NEITHER PARTY WILL BE LIABLE FOR INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL DAMAGES, OR FOR LOST PROFITS, REVENUE, GOODWILL, OR DATA, EVEN IF ADVISED OF THE POSSIBILITY. EACH PARTY’S TOTAL LIABILITY ARISING OUT OF OR RELATING TO THE SERVICES WILL NOT EXCEED THE AMOUNTS CUSTOMER PAID OR PAYABLE TO VIRENT FOR THE SERVICES IN THE 12 MONTHS BEFORE THE EVENT GIVING RISE TO LIABILITY, OR US$100 IF CUSTOMER PAID NOTHING. These limits do not apply to liability that cannot lawfully be limited, Customer’s payment obligations, or a party’s fraud or willful misconduct. A written order form may state different limits. ## Indemnity To the extent permitted by law, Customer will defend and indemnify Virent and its personnel from third-party claims arising from Customer Data, Customer’s websites or products, Customer’s breach of these Terms, or Customer’s unlawful or unauthorized use of the Services. Virent will provide prompt notice and reasonable cooperation, and Customer may control the defense, provided no settlement admits fault by or imposes obligations on Virent without consent. ## General terms Neither party may assign the agreement without the other’s consent, except in connection with a merger, reorganization, sale of substantially all assets, or to an affiliate, provided the assignee assumes the obligations. The parties are independent contractors. Failure to enforce a provision is not a waiver. If a provision is unenforceable, it will be modified to the minimum extent necessary and the rest remains effective. Neither party is liable for delay caused by events beyond reasonable control. Notices may be provided electronically. Governing law and venue stated in an order form control. If none is stated, applicable conflict-of-law and mandatory consumer-protection rules determine governing law and a court with competent jurisdiction may hear the dispute. These Terms and incorporated agreements are the entire agreement regarding the Services. ## Changes and contact We may update these Terms. Material changes will apply prospectively after reasonable notice, unless an earlier effective date is required for law or security. Continued use after the effective date constitutes acceptance where permitted. Questions and legal notices should be sent to virent.app@gmail.com. Our registered office is 2140 S Dupont Hwy, Camden, DE 19934, USA. ## Related - [Privacy Policy](https://virent.app/privacy) - [Data Processing Addendum](https://virent.app/dpa) - [Contact](https://virent.app/contact): Privacy, legal and security contact paths. --- # Data Processing Addendum > This Data Processing Addendum governs Virent’s processing of personal data on behalf of a customer using the Services. Canonical: https://virent.app/dpa Last updated: 2026-10-27 Effective October 27, 2026. ## Application and incorporation This Data Processing Addendum (“DPA”) forms part of the Terms of Service or other agreement between L Partner Corp, a Delaware corporation doing business as Virent (“Virent”) and Customer (the “Agreement”) when Virent processes Customer Personal Data as a processor or service provider. It is effective when Customer accepts the Agreement or the parties reference it in an order form. Capitalized terms not defined here have the meaning in the Agreement. If this DPA conflicts with the Agreement on processing Customer Personal Data, this DPA controls. ## Definitions - “Applicable Data Protection Law” means privacy and data protection law applicable to the processing, including Regulation (EU) 2016/679 (GDPR), the UK GDPR and Data Protection Act 2018, the Swiss Federal Act on Data Protection, Brazil’s Lei Geral de Proteção de Dados Pessoais (Law No. 13,709/2018 or LGPD) and ANPD regulations, applicable United States state privacy laws, and implementing or successor regulations. - “Customer Personal Data” means personal data contained in Customer Data that Virent processes on Customer’s behalf. - “Controller,” “processor,” “controlador,” “operador,” “business,” “service provider,” “consumer,” “data subject,” “titular,” “personal data,” “process,” “processing agent,” and “supervisory authority” have the meanings given by Applicable Data Protection Law. - “Security Incident” means a confirmed breach of security leading to accidental or unlawful destruction, loss, alteration, unauthorized disclosure of, or access to Customer Personal Data. It excludes unsuccessful attempts that do not compromise data. - “Subprocessor” means a third party engaged by Virent to process Customer Personal Data. ## Roles and processing instructions Customer is the controller, controlador, or business and Virent is the processor, operador, or service provider, except where Customer acts as a processor or operador for another controller, in which case Virent is Customer’s subprocessor or suboperator. Customer is responsible for its instructions, lawful basis, notices, consents, data-subject choices, records of processing, and the legality of Customer Personal Data. Virent will process Customer Personal Data only on Customer’s documented instructions, including the Agreement, Customer’s configuration and use of the Services, and other written instructions consistent with the Agreement. Virent will notify Customer if it believes an instruction violates Applicable Data Protection Law, unless prohibited from doing so. ## Processing details ### Subject matter and duration Providing, securing, supporting, and improving the contracted Services for the term of the Agreement and the deletion period described below. ### Nature and purpose Hosting, collecting, organizing, classifying, querying, comparing, transmitting, securing, and deleting Customer Personal Data to provide human analytics, crawler analytics, LLM visibility, prompt and citation tracking, content research, drafting, review, and publishing of Customer-approved content, integrations, reporting, and support selected by Customer. ### Categories of data - Account identifiers and business contact information. - Online identifiers, pseudonymous IDs, device or browser context, referral information, event and conversion data. - Request URL, user-agent, response metadata, timestamps, bot classification, and derived or transient network context. - Prompts, answers, mentions, citations, domains, competitor information, annotations, and configuration data. - Brand context, research queries, retrieved public-page snapshots and excerpts, search-demand and results-page observations, briefs, drafts, revisions, claim checks, approvals, and publication records. - Repository identifiers, file paths, and repository content that Virent reads or writes for an approved publication to a connected GitHub repository. - Support content and any other personal data Customer chooses to submit consistently with the Agreement. ### Data subjects - Customer’s authorized users, personnel, contractors, prospects, and contacts. - Visitors and users of Customer-controlled websites or applications. - Individuals referenced in Customer-submitted prompts, content, support requests, or public-source analysis. ### Sensitive data The Services are not designed for sensitive personal data. Customer will not submit special-category data, protected health information, payment-card data, government identifiers, precise location, passwords, or similar sensitive data unless the parties expressly agree in writing to additional safeguards. ## Virent obligations - Ensure personnel authorized to process Customer Personal Data are bound by confidentiality obligations. - Implement and maintain technical and organizational measures appropriate to the risk. - Assist Customer, taking into account the nature of processing and information available to Virent, with data-subject requests, security, breach notifications, impact assessments, and regulator consultations required by Applicable Data Protection Law. - Make information reasonably necessary to demonstrate compliance with this DPA available to Customer. - Not sell Customer Personal Data, share it for cross-context behavioral advertising, retain, use, or disclose it outside the business purposes in the Agreement, or combine it with personal data from other sources except as permitted for a service provider by applicable law. ## Security measures Virent will maintain safeguards appropriate to the Services, processing scope, and risk. Measures may evolve without materially reducing the overall level of protection during a paid subscription term. - Access controls based on role and need, authentication protections, and protected production credentials. - Encryption in transit using current industry-standard transport protocols and encryption at rest where supported by the applicable storage layer. - Data minimization, pseudonymous identifiers where appropriate, separation of customer workspaces, and controls intended to prevent unauthorized access. - Logging, monitoring, vulnerability and dependency management, backup and recovery practices, and documented incident response. - Vendor review and contractual data-protection obligations for relevant Subprocessors. - Secure development, change review, and testing practices proportionate to the risk of the change. ## Subprocessors Customer gives Virent general authorization to engage Subprocessors needed to provide the Services. Virent remains responsible for each Subprocessor’s performance of data protection obligations to the extent required by Applicable Data Protection Law and will impose written obligations that provide materially similar protection. Virent will provide a current Subprocessor list on request and, for customers with a paid order form, notice of a new Subprocessor before it processes Customer Personal Data where required. Customer may object on reasonable data-protection grounds by emailing virent.app@gmail.com within 15 days of notice. The parties will work in good faith on a commercially reasonable solution; if none is available, either party may terminate the affected Service. ### Current Subprocessors The following Subprocessors are engaged as of this DPA’s effective date. Some process Customer Personal Data only when Customer uses the related feature. - Vercel: application hosting and functions; Vercel AI Gateway for routing requests to AI model providers. - PlanetScale: primary database for accounts, configuration, and product records. - Upstash: caching, rate limiting, and background job delivery. - Resend: transactional email. - AI model providers reached through Vercel AI Gateway for the models a workspace enables, currently models from OpenAI, Anthropic, Google, xAI, Perplexity, DeepSeek, and Meta. They receive the prompts and content needed for visibility monitoring and, when Content Agent is used, research, drafting, and evaluation. AI Gateway may route a request to the model’s developer or another inference host. - Firecrawl: searching for and fetching public web pages for content research and website previews. - DataForSEO, when the related feature is enabled: for visibility monitoring, it receives tracked prompts as search queries in the website’s markets and returns search-results-page and AI answer data (Google AI Overviews and the results page around it); for Content Agent research, it receives keywords and domains and returns search-demand, keyword, domain, and results-page data (DataForSEO Labs and SERP); for AI answer monitoring, it receives prompts, brand names, and domains and returns AI answer and mention data (AI Optimization, including LLM Mentions and LLM Scraper); and for link research, it receives domains and returns backlink data (Backlinks). - GitHub: publishing approved content to repositories Customer connects through the Virent GitHub App. Access is limited to the repositories and permissions Customer grants when installing the app. ## Data-subject requests Taking into account the nature of processing, Virent will provide reasonable assistance for Customer to respond to requests to confirm processing; access, correct, anonymize, block, delete, restrict, object to, or port Customer Personal Data; obtain information about sharing; withdraw consent; or exercise rights related to qualifying automated decisions. If Virent receives a request directly, it will direct the requester to Customer unless law requires another response. Customer is responsible for responding within applicable time limits and for using available Service controls before requesting additional assistance. ## Security Incidents Virent will notify Customer without undue delay after becoming aware of a Security Incident affecting Customer Personal Data. Notice will be sent to Customer’s account contact or virent.app@gmail.com correspondence channel and will include available information reasonably needed for Customer’s obligations, such as the nature of the incident, affected data, likely consequences, and mitigation. Virent may provide information in phases as it becomes available. Virent’s notice or response is not an admission of fault or liability. Customer is responsible for notices to individuals, regulators, or others unless law assigns that duty to Virent. This includes, where the Customer is a Brazilian controlador and the legal threshold is met, notice to the ANPD and affected data subjects within the period required by ANPD rules, currently three business days under Resolution CD/ANPD No. 15/2024. ## Deletion and return During the term, Customer may use available export and deletion controls. After termination or a valid written request, Virent will delete or return Customer Personal Data within a commercially reasonable period unless law requires retention. Data may remain temporarily in protected backups until overwritten under normal cycles and will remain subject to this DPA. Virent may retain de-identified data that cannot reasonably be linked to Customer or an individual. Default retention periods, unless the Agreement or a workspace setting specifies otherwise: human analytics events 395 days; crawler analytics events 90 days; usage records 730 days; raw web pages fetched for content research 90 days, or less where the source’s terms require; approved article revisions and permitted supporting excerpts until the article is deleted; operational logs 30 days. Audit and billing records are kept as long as contractual, legal, or accounting requirements need. Content that Customer approved and Virent published to a Customer-controlled repository or other remote destination is under Customer’s control. Deleting it in the Services does not delete or revert the remote copy, and Virent does not reverse remote publications automatically. ## Audits and compliance information Virent will respond to reasonable written security and compliance questionnaires and provide available independent reports or summaries under confidentiality where appropriate. If that information is insufficient, Customer may request an audit no more than once per year, or after a Security Incident, by an independent auditor bound by confidentiality. Audits must be coordinated in advance, avoid disruption, protect other customers, and be at Customer’s expense unless the audit identifies a material breach by Virent. No audit may provide access to another customer’s data, penetration-test production without written approval, or compromise security. ## International transfers When Virent transfers Customer Personal Data from the EEA, United Kingdom, or Switzerland to a country without an applicable adequacy decision, the parties incorporate the legally required transfer mechanism. For EEA transfers, this includes the European Commission Standard Contractual Clauses adopted by Decision (EU) 2021/914, using Module Two or Module Three as appropriate. For UK transfers, the applicable UK Addendum is incorporated. Swiss law adaptations apply where required. The information in this DPA and the Agreement completes the relevant annexes: Customer is the exporter, Virent is the importer, the processing details appear above, the competent authority and governing law are selected as required by the applicable clauses, and the security measures are described in this DPA. If the transfer clauses conflict with this DPA, the transfer clauses control. For a transfer of Customer Personal Data from Brazil that requires contractual safeguards, the parties will use the Brazilian standard contractual clauses in Annex II to ANPD Resolution CD/ANPD No. 19/2024 in full and without modification, or another transfer mechanism valid under the LGPD. The parties’ identities, roles, transfer description, security measures, and contact channels will be completed from this DPA and the applicable order form. The mandatory Brazilian clauses control over conflicting terms. Virent will reasonably assist Customer with the transparency information and copy of transfer clauses that the LGPD and ANPD rules require. ## Jurisdiction-specific terms ### EEA Article 28 GDPR requirements apply where relevant. Virent will assist with data-subject rights, security obligations, data protection impact assessments, and prior consultations, taking into account the nature of processing and information available to Virent. The applicable EU SCC module and supervisory authority are determined by the parties’ roles and the data exporter’s establishment. ### United Kingdom and Switzerland References to GDPR obligations include the corresponding UK GDPR or Swiss requirements where applicable. Restricted UK transfers use the UK International Data Transfer Agreement or the approved UK Addendum to the EU SCCs, as appropriate. Swiss transfers use the EU SCCs with adaptations required by Swiss law where permitted. ### Brazil For LGPD-covered processing, Customer is the controlador and Virent is the operador unless the facts require another classification. Virent will follow Customer’s lawful instructions, maintain security and governance measures appropriate to risk, assist with titular requests and impact assessments, and provide information reasonably necessary for Customer’s accountability obligations. Customer remains responsible for selecting a lawful basis, meeting transparency duties, responding to titulares, and making required communications to the ANPD. ### United States Where state privacy law applies, Virent acts as a service provider, contractor, or processor for Customer Personal Data; processes it only for the limited and specified purposes in the Agreement; does not sell it or share it for cross-context behavioral advertising; and will provide the same level of privacy protection required by applicable law. Customer may take reasonable steps to verify compliant use and require remediation of unauthorized use. ## Liability, term, and contact Each party’s liability under this DPA is subject to the exclusions and limitations in the Agreement to the extent permitted by law. This DPA remains in effect while Virent processes Customer Personal Data. Changes required by law may take effect upon notice; other material changes require agreement where applicable. Data protection questions, requests for the Subprocessor list, and DPA notices should be sent to virent.app@gmail.com. ## Related - [Privacy Policy](https://virent.app/privacy) - [Terms of Service](https://virent.app/terms) - [Contact](https://virent.app/contact): Privacy, legal and security contact paths.