Introduction

Convrs is a lightweight website analytics platform built for modern SaaS products.

Add a single script to your website and start tracking visitors, pageviews, conversions, custom events, and revenue attribution in real time.

See the Quickstart guide to get set up in under two minutes.

Quick Start

Get started with Convrs in under two minutes.

1. Create a Website

Create a website in your Convrs dashboard and copy your Website ID.

2. Add the Script

Paste the script into your website's <head> or before the closing </body> tag.

1
2
3
4
5
<script
  async
  src="https://convrs.dev/script.js"
  data-website-id="YOUR_WEBSITE_ID">
</script>

3. Open Your Dashboard

Visit your Convrs dashboard and start exploring your analytics.

Data typically appears within a few seconds of the first pageview.

Replace YOUR_WEBSITE_ID with the Website ID from your Convrs dashboard.

HTML & Vanilla JS

The simplest installation — add the Convrs tracking script anywhere in your HTML.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
  <head>
    <title>My Site</title>

    <!-- Convrs Analytics -->
    <script
      async
      src="https://convrs.dev/script.js"
      data-website-id="YOUR_WEBSITE_ID">
    </script>
  </head>

  <body>
    <!-- Your content -->
  </body>
</html>

Using async ensures the script never blocks page rendering.

Next.js

Use the built-in Next.js Script component so Convrs loads with the correct strategy.

App Router (Next.js 13+)

Add this to your app/layout.tsx:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Script from 'next/script';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        {children}

        <Script
          src="https://convrs.dev/script.js"
          data-website-id="YOUR_WEBSITE_ID"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

Pages Router

Add this to pages/_app.tsx:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import Script from 'next/script';
import type { AppProps } from 'next/app';

export default function App({
  Component,
  pageProps,
}: AppProps) {
  return (
    <>
      <Component {...pageProps} />

      <Script
        src="https://convrs.dev/script.js"
        data-website-id="YOUR_WEBSITE_ID"
        strategy="afterInteractive"
      />
    </>
  );
}

Convrs automatically tracks client-side route changes in Next.js.

React (Vite / CRA)

Install Convrs in your React application to start tracking pageviews, visitors, and custom events automatically.

The simplest approach is to add the Convrs script directly to your index.html file.

Vite

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My App</title>
  </head>

  <body>
    <div id="root"></div>

    <script
      async
      src="https://convrs.dev/script.js"
      data-website-id="YOUR_WEBSITE_ID">
    </script>

    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

Create React App

1
2
3
4
5
6
7
8
9
10
11
<!-- public/index.html -->

<body>
  <div id="root"></div>

  <script
    async
    src="https://convrs.dev/script.js"
    data-website-id="YOUR_WEBSITE_ID">
  </script>
</body>

Option B — Load via useEffect

If you prefer to load Convrs dynamically, add the script once when your application mounts.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { useEffect } from 'react';

export default function App() {
  useEffect(() => {
    const script = document.createElement('script');

    script.src = 'https://convrs.dev/script.js';
    script.async = true;

    script.setAttribute(
      'data-website-id',
      'YOUR_WEBSITE_ID'
    );

    document.head.appendChild(script);

    return () => {
      document.head.removeChild(script);
    };
  }, []);

  return <div>Your App</div>;
}

Vue.js

1
2
3
4
5
6
7
8
9
10
11
<body>
  <div id="app"></div>

  <script
    async
    src="https://convrs.dev/script.js"
    data-website-id="YOUR_WEBSITE_ID">
  </script>

  <script type="module" src="/src/main.ts"></script>
</body>

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script setup>
import { onMounted } from 'vue';

onMounted(() => {
  const script = document.createElement('script');

  script.src = 'https://convrs.dev/script.js';
  script.async = true;

  script.setAttribute(
    'data-website-id',
    'YOUR_WEBSITE_ID'
  );

  document.head.appendChild(script);
});
</script>

<template>
  <RouterView />
</template>

Convrs automatically tracks Vue Router navigation.

Nuxt.js

Use Nuxt's built-in head management to load Convrs on every page.

1
2
3
4
5
6
7
8
9
10
11
12
13
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          src: 'https://convrs.dev/script.js',
          'data-website-id': 'YOUR_WEBSITE_ID',
          async: true,
        },
      ],
    },
  },
});

app.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script setup>
useHead({
  script: [
    {
      src: 'https://convrs.dev/script.js',
      'data-website-id': 'YOUR_WEBSITE_ID',
      async: true,
    },
  ],
});
</script>

<template>
  <NuxtPage />
</template>

Convrs automatically tracks Nuxt route changes.

SvelteKit

Add the Convrs script to your root layout.

1
2
3
4
5
6
7
8
9
10
11
<!-- src/routes/+layout.svelte -->

<svelte:head>
  <script
    async
    src="https://convrs.dev/script.js"
    data-website-id="YOUR_WEBSITE_ID">
  </script>
</svelte:head>

<slot />

Convrs automatically tracks client-side navigation and page changes.

Remix

Add Convrs to your root application layout.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import {
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";

export default function App() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />

        <script
          async
          src="https://convrs.dev/script.js"
          data-website-id="YOUR_WEBSITE_ID"
        />
      </head>

      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

Convrs automatically tracks route transitions in Remix applications.

Astro

Add Convrs to your base layout.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
---
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />

    <script
      async
      src="https://convrs.dev/script.js"
      data-website-id="YOUR_WEBSITE_ID">
    </script>

    <slot name="head" />
  </head>

  <body>
    <slot />
  </body>
</html>

If you're using Astro View Transitions, add transition:persist to the script tag to prevent reinitialization.

Gatsby

Install Convrs globally using Gatsby SSR APIs.

gatsby-ssr.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from "react";

export const onRenderBody = ({
  setHeadComponents,
}) => {
  setHeadComponents([
    <script
      key="convrs"
      async
      src="https://convrs.dev/script.js"
      data-website-id="YOUR_WEBSITE_ID"
    />,
  ]);
};

gatsby-browser.js

1
2
// Convrs automatically tracks route changes.
// No additional setup is required.

Gatsby uses the History API, which Convrs tracks automatically.

WordPress

There are two ways to install Convrs on WordPress.

Option A — functions.php

1
2
3
4
5
function convrs_analytics_script() {
    echo '<script async src="https://convrs.dev/script.js" data-website-id="YOUR_WEBSITE_ID"></script>';
}

add_action('wp_head', 'convrs_analytics_script');

Option B — Plugin

Install a plugin such as:

  • Insert Headers and Footers
  • WPCode

Then paste:

1
2
3
4
5
<script
  async
  src="https://convrs.dev/script.js"
  data-website-id="YOUR_WEBSITE_ID">
</script>

into the Header section.

If you're using caching plugins such as WP Rocket or W3 Total Cache, ensure the script remains present in cached pages.

Webflow

Webflow allows custom code to be added globally across your site.

Installation

  1. Open your Webflow project.
  2. Click Project Settings.
  3. Open the Custom Code tab.
  4. Paste the following into Head Code:
1
2
3
4
5
<script
  async
  src="https://convrs.dev/script.js"
  data-website-id="YOUR_WEBSITE_ID">
</script>
  1. Save changes.
  2. Republish your website.

Convrs will immediately begin tracking pageviews once your site is published.

Shopify

Install Convrs across your entire Shopify storefront.

Installation

  1. Open your Shopify Admin.
  2. Navigate to Online Store → Themes.
  3. Select Actions → Edit Code.
  4. Open layout/theme.liquid.
  5. Paste the following before the closing </head> tag:
1
2
3
4
5
<script
  async
  src="https://convrs.dev/script.js"
  data-website-id="YOUR_WEBSITE_ID">
</script>
  1. Save the file.

Convrs automatically tracks storefront pages including product pages, collection pages, cart pages, and landing pages.

Convrs does not track activity inside the Shopify Admin dashboard.

NPM SDK

Install Convrs as an npm package for type-safe analytics tracking in JavaScript and TypeScript applications.

Perfect for React, Next.js, Vue, Nuxt, SvelteKit, Remix, Astro, and other modern web frameworks.

Why use the SDK?

  • TypeScript support
  • Framework agnostic
  • Automatic pageview tracking
  • User identification
  • Offline-ready

Installation

1
npm install @convrs/sdk

Quick Start

1
2
3
4
5
import { initConvrs } from "@convrs/sdk";

const convrs = await initConvrs({
  websiteId: "YOUR_WEBSITE_ID",
});

Track Events

1
2
3
convrs.track("signup", {
  source: "homepage",
});

Identify Users

1
2
3
4
convrs.identify("user_123", {
  email: "user@example.com",
  plan: "pro",
});

React / Next.js Example

lib/analytics.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { initConvrs } from "@convrs/sdk";

let convrs: any = null;

export async function getAnalytics() {
  if (!convrs) {
    convrs = await initConvrs({
      websiteId:
        process.env.NEXT_PUBLIC_CONVRS_WEBSITE_ID!,
      autoCapturePageviews: true,
    });
  }

  return convrs;
}

Automatic Pageview Tracking

1
2
3
4
const convrs = await initConvrs({
  websiteId: "YOUR_WEBSITE_ID",
  autoCapturePageviews: true,
});

Configuration Options

OptionTypeDescription
websiteIdstringYour Convrs website ID
domainstringOverride the current hostname
apiUrlstringCustom ingestion endpoint
debugbooleanEnable debug logging
allowLocalhostbooleanEnable localhost tracking
allowIframebooleanEnable tracking inside iframes
allowedHostnamesstring[]Domains used for cross-domain tracking

Example Configuration

1
2
3
4
5
6
7
8
9
const convrs = await initConvrs({
  websiteId: "YOUR_WEBSITE_ID",
  debug: true,
  allowLocalhost: true,

  autoCapturePageviews: {
    trackHashChanges: true,
  },
});

See the API Reference for track(), identify(), trackPageview(), flush(), reset(), and cross-domain tracking.

Script Options

The Convrs tracking script accepts several optional data-* attributes to customize its behavior.

AttributeRequiredDescription
data-website-idYesYour unique Website ID from the Convrs dashboard.
data-apiNoOverride the default tracking endpoint. Useful for custom domains, proxies, or self-hosted ingestion.
data-debugNoEnable debug logging in the browser console.
data-allow-localhostNoEnable tracking while running on localhost.

Example

1
2
3
4
5
6
7
8
9
<script
  async
  src="https://convrs.dev/script.js"
  data-website-id="YOUR_WEBSITE_ID"
  data-api="https://analytics.yourdomain.com/api/track"
  data-debug="true"
  data-allow-localhost="true"
  data-allow-file-protocol="true">
</script>

Only data-website-id is required. All other attributes are optional and should only be used when needed.

API Reference

The Convrs SDK exposes a simple API for tracking events, pageviews, and user identification.

track()

Track a custom event.

Syntax

1
convrs.track(eventName, properties?)

Parameters

ParameterTypeDescription
eventNamestringName of the event.
propertiesobjectOptional event metadata.

Examples

1
convrs.track("signup");
1
2
3
4
5
convrs.track("purchase", {
  amount: 99,
  currency: "USD",
  plan: "Pro",
});

identify()

Associate events with a user.

Syntax

1
convrs.identify(userId, traits?)

Parameters

ParameterTypeDescription
userIdstringUnique identifier for the user.
traitsobjectOptional user attributes.

Examples

1
convrs.identify("user_123");
1
2
3
4
5
convrs.identify("user_123", {
  email: "user@example.com",
  name: "John Doe",
  plan: "Pro",
});

trackPageview()

Manually track a pageview.

Most applications do not need this because pageviews are tracked automatically when autoCapturePageviews is enabled.

Track Current Page

1
convrs.trackPageview();

Track Custom Path

1
convrs.trackPageview("/pricing");

flush()

Immediately send all queued events.

Syntax

1
await convrs.flush();

Example

1
await convrs.flush();

Useful before:

  • Page unloads
  • Checkout redirects
  • Critical conversion events

reset()

Reset the current visitor and session.

Syntax

1
convrs.reset();

Example

1
2
3
function logout() {
  convrs.reset();
}

Useful when a user logs out.

getConvrsClient()

Access the initialized Convrs client anywhere in your application.

Syntax

1
2
3
import { getConvrsClient } from "@convrs/sdk";

const convrs = getConvrsClient();

Example

1
2
3
4
5
import { getConvrsClient } from "@convrs/sdk";

const convrs = getConvrsClient();

convrs.track("feature_used");

buildCrossDomainUrl()

Generate a URL containing Convrs tracking parameters.

Syntax

1
convrs.buildCrossDomainUrl(url);

Example

1
2
3
const url = convrs.buildCrossDomainUrl(
  "https://app.example.com/signup"
);

Result:

1
https://app.example.com/signup?_cv_vid=xxx&_cv_sid=xxx

getTrackingParams()

Retrieve the current visitor and session identifiers.

Syntax

1
const params = convrs.getTrackingParams();

Example

1
2
3
const params = convrs.getTrackingParams();

console.log(params);

Result:

1
2
3
4
{
  visitorId: "visitor_123",
  sessionId: "session_456"
}

Complete Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { initConvrs } from "@convrs/sdk";

const convrs = await initConvrs({
  websiteId: "YOUR_WEBSITE_ID",
});

convrs.identify("user_123", {
  plan: "Pro",
});

convrs.track("signup");

convrs.track("purchase", {
  amount: 99,
  currency: "USD",
});

await convrs.flush();

Tracking Events

Beyond automatic pageview tracking, Convrs lets you send custom events to measure important user actions throughout your application.

Custom events can be used to track:

  • Signups
  • Purchases
  • Feature usage
  • Form submissions
  • Button clicks
  • Checkout flow events
  • Marketing conversions

All custom events appear in your Convrs dashboard and can be used for funnels, conversion tracking, and revenue attribution.

Syntax

1
window.convrs(eventName, properties)
ParameterTypeDescription
eventNamestringName of the event to track.
propertiesobjectOptional metadata associated with the event.

Event names should be descriptive and consistent. Examples: signup, purchase, invite_sent, checkout_started.

Event Examples

Button Click

1
2
3
<button onclick="window.convrs('cta_clicked', { location: 'hero' })">
  Get Started
</button>

Form Submission

1
2
3
4
5
document
  .querySelector('#signup-form')
  .addEventListener('submit', () => {
    window.convrs('signup_submitted');
  });

React — Button Click

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function UpgradeButton() {
  function handleClick() {
    window.convrs('upgrade_clicked', {
      plan: 'pro',
      source: 'pricing_page',
    });

    // Open checkout
  }

  return (
    <button onClick={handleClick}>
      Upgrade to Pro
    </button>
  );
}

E-commerce — Add to Cart

1
2
3
4
5
6
window.convrs('add_to_cart', {
  product_id: 'sku_1234',
  product_name: 'Wireless Headphones',
  price: 79.99,
  currency: 'USD',
});

Purchase Completed

1
2
3
4
5
6
window.convrs('purchase', {
  order_id: 'order_123',
  amount: 99,
  currency: 'USD',
  plan: 'pro',
});

Video Played

1
2
3
4
5
6
7
document
  .querySelector('#hero-video')
  .addEventListener('play', () => {
    window.convrs('video_played', {
      video: 'hero_demo',
    });
  });

Checkout Started

1
2
3
4
window.convrs('checkout_started', {
  plan: 'pro',
  billing_cycle: 'monthly',
});

Invite Sent

1
2
3
window.convrs('invite_sent', {
  team_size: 5,
});

Event Properties

Properties provide additional context for an event.

1
2
3
4
5
window.convrs('signup', {
  plan: 'pro',
  source: 'pricing_page',
  campaign: 'summer_launch',
});

These properties can be used to better understand user behavior and conversion patterns.

Best Practices

  • Use lowercase event names.
  • Use snake_case for event names.
  • Keep event names consistent across your application.
  • Attach meaningful properties to important events.
  • Avoid sending sensitive user information.

Good examples:

1
2
3
4
window.convrs('signup');
window.convrs('checkout_started');
window.convrs('purchase');
window.convrs('invite_sent');

Avoid:

1
2
3
window.convrs('Clicked Button');
window.convrs('Event 1');
window.convrs('test');

Convrs automatically tracks pageviews and route changes. Custom events should be used for actions that represent meaningful user behavior.

Modern AI tools read your site before most humans do. ChatGPT fetches your pricing page to answer a question about it, Googlebot re-indexes your docs, GPTBot pulls your blog for training data — Bot traffic tracking shows you all of it, broken down by who's asking and why.

Bot traffic tracking is included in your Convrs plan. It isn't a separate add-on.

Get started

Install the server-side package, add one call to your backend, deploy. This runs separately from Convrs's normal browser tracking script — bots skip your frontend JavaScript, so this has to run server-side.

Install @convrs/ai-bot-sdk on npm

1. Install

1
npm install @convrs/ai-bot-sdk

2. Add it to your server

Most common setup — Next.js middleware:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// middleware.ts
import { createBotTrackingMiddleware } from "@convrs/ai-bot-sdk";

const trackBots = createBotTrackingMiddleware({
  siteId: "YOUR_SITE_ID",
});

export function middleware(
  request: Request,
  context: { waitUntil: (p: Promise<unknown>) => void }
) {
  trackBots(request, context);
}

export const config = {
  // Keep crawler-facing files reachable: robots.txt, llms.txt, sitemaps.
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};

Don't await trackBots(...). Call it, let it run in the background, and return your response immediately. Passing context lets the SDK use waitUntil internally so tracking never adds latency to the real response.

3. Deploy and check your dashboard

After deploying, open your Convrs dashboard and look for the Bot traffic card. Filter by AI Answers, Indexing, or Training, and switch between the timeline and the per-provider breakdown.

If nothing shows up right away, that's expected — you're waiting for a real crawler to visit, not a human pageview. Try curl-ing your own site with a known bot's user-agent to confirm the pipeline end to end (see Testing your setup below).

What gets tracked

Every detected bot is classified into one of four categories:

CategoryExampleWhat it tells you
AI answers (answer_agent)A user asks ChatGPT about your product; ChatGPT-User fetches your pricing page to answer accurately.Which pages AI assistants pull in real time to answer user questions.
Indexing (index_crawler)Googlebot or PerplexityBot requests a page to refresh a search or answer index.Who's discovering and re-indexing your content.
Training (training_crawler)GPTBot, ClaudeBot, Applebot, or Bytespider requests public pages.Who's collecting your content for model training or large datasets.
Other (other)Anything recognized as bot traffic that doesn't cleanly fit the three buckets above.Catch-all so nothing silently disappears from the dashboard.

Classification covers 20+ vendors out of the box — OpenAI, Anthropic, Google, Perplexity, Microsoft, Apple, Amazon, Meta, xAI, Mistral, Baidu, Alibaba, ByteDance, DeepSeek, Cohere, Common Crawl, and more. New vendors get added to the SDK's registry over time with no config change needed on your end.

If a crawler keeps requesting a page that doesn't exist — /pricing-old, /docs/quickstart — that's a signal worth acting on. It usually means users or agents expect that page to exist somewhere.

Crawler-facing files

These are always tracked when a known bot requests them, even though they'd normally be filtered out as "not a real page":

  • /robots.txt
  • /llms.txt and /llms-full.txt
  • /sitemap.xml and other sitemap files
  • Any path ending in .xml under /sitemap/ or /sitemaps/

Everything else under your default-ignored prefixes (/api, /_next, /static, /assets, and similar) and default-ignored file extensions (.css, .js, .png, etc.) is skipped, since those are near-never what a person actually means by "did a bot visit my site."

How it works

On every request, the SDK checks the method, the User-Agent, and the path — in that order, bailing out as early as possible — before deciding whether to send anything:

  1. Is this a GET/HEAD request? (configurable)
  2. Does the User-Agent match a known bot? If not, stop here — nothing is sent.
  3. Is the path a static asset, an ignored prefix, or over the length limit?
  4. Send a small event in the background and return immediately.

The event itself only carries the raw User-Agent, IP, URL, and status code — vendor and category are always re-derived on the server, not trusted from the client. That keeps a caller from spoofing, say, a training crawler as an answer agent, and means crawler definitions can be updated on Convrs's side without every integration needing a package bump.

Tracking is best-effort. If the ingest endpoint is slow or unreachable, the SDK gives up quietly after a short timeout — it will never delay or break your actual response.

Platform examples

Next.js middleware

See Get started above.

Express

1
2
3
4
5
6
import express from "express";
import { createExpressBotMiddleware } from "@convrs/ai-bot-sdk";

const app = express();

app.use(createExpressBotMiddleware({ siteId: "YOUR_SITE_ID" }));

The Express adapter calls next() immediately, then attaches a finish listener and sends the event after your response has already gone out — your request handler never waits on it.

Generic Request/Response handler

If your framework gives you a request object up front and a response object later:

1
2
3
4
5
6
7
8
import { withBotTracking } from "@convrs/ai-bot-sdk";

export const GET = withBotTracking(
  async (request: Request) => {
    return new Response("ok");
  },
  { siteId: "YOUR_SITE_ID" }
);

If you only have the request and not the eventual response, request-only tracking still captures which page the bot hit — it just won't include a status code:

1
2
3
4
5
import { trackBotRequest } from "@convrs/ai-bot-sdk";

export function middleware(request: Request, context: { waitUntil: Function }) {
  trackBotRequest(request, context, { siteId: "YOUR_SITE_ID" });
}

Custom hosts behind an internal hostname

If your runtime hands the SDK an internal address (localhost, 0.0.0.0) instead of your public one, set it explicitly:

1
2
3
4
trackBotRequest(request, context, {
  siteId: "YOUR_SITE_ID",
  publicOrigin: "https://example.com",
});

Convrs still validates the resulting hostname against your site configuration and preserves the original path and query string.

Use without Node.js

Any backend that can send an HTTPS POST can report crawler traffic directly — no npm package required.

1
2
3
POST https://ingest.convrs.dev/api/ai-crawls
Content-Type: application/json
Authorization: Bearer cvbot_...    (only if you've enabled required auth)

Request body:

1
2
3
4
5
6
7
8
9
10
11
12
{
  "siteId": "YOUR_SITE_ID",
  "domain": "example.com",
  "url": "https://example.com/docs/get-started",
  "referrer": null,
  "bot": {
    "userAgent": "Mozilla/5.0 ... ChatGPT-User/1.0",
    "ip": "203.0.113.10",
    "statusCode": 200,
    "source": "server_middleware"
  }
}
FieldRequiredNotes
siteIdYesYour project token. websiteId is accepted as an alias.
urlYesAbsolute URL the crawler requested. Hostname must belong to your site.
domainRecommendedHostname that received the request. Falls back to the URL's own hostname if omitted.
bot.userAgentYesFull raw User-Agent string. Classification happens from this alone.
bot.ipRecommendedCrawler's source IP as seen by your server.
bot.statusCodeOptionalYour response status, 100-599. Omit if unavailable.
bot.sourceOptionalFree-form label for where this came from, e.g. server_middleware.

Don't send vendor, agentName, or category — even if you compute them yourself. They're always re-derived server-side and any value you send is ignored, by design.

A tracked-or-safely-ignored request returns 202 with a body indicating whether it was actually recognized as a bot:

1
{ "success": true, "tracked": true, "category": "training_crawler" }

or, for a user-agent that isn't a known bot:

1
{ "success": true, "tracked": false, "reason": "not_a_bot" }

Optional request authentication

Add a site-specific token without touching your existing integration:

  1. Open your Bot traffic card settings and generate a token.
  2. Add it to your SDK config or raw HTTP header.
  3. Once deployed, flip on Reject unauthenticated requests.
1
2
3
4
createBotTrackingMiddleware({
  siteId: "YOUR_SITE_ID",
  authToken: process.env.CONVRS_BOT_TOKEN,
});

Keep the cvbot_... token server-side only — never in frontend code, a public repo, logs, or a URL. Enforcement is off until you explicitly enable it, so adding a token doesn't change existing behavior on its own. Rotating or deleting the token takes effect immediately.

Filtering categories

By default every category is tracked. Turn individual ones off if you only care about specific crawler types:

1
2
3
4
5
6
7
createBotTrackingMiddleware({
  siteId: "YOUR_SITE_ID",
  skipAnswerAgents: true,
  skipIndexCrawlers: true,
  skipTrainingCrawlers: true,
  skipOtherBots: true,
});

Most sites should leave the defaults on and filter later in the dashboard — turning a category off here means that traffic is never sent at all, not just hidden.

Privacy checklist

  • Call the ingest endpoint (directly or via the SDK) only from your backend. Never from browser JavaScript, and never for regular human traffic.
  • The SDK only ever sends the fields listed above — it doesn't forward cookies, auth headers, request bodies, or other visitor data.
  • Prefer URLs without query parameters where you can. If query params carry anything sensitive, strip them before the URL reaches the SDK.
  • Treat any IP you pass as untrusted unless it's coming through a proxy you control that strips client-supplied forwarding headers.

Testing your setup

1
2
3
curl -X POST https://ingest.convrs.dev/api/ai-crawls \
  -H "Content-Type: application/json" \
  -d '{"siteId":"YOUR_SITE_ID","url":"https://example.com/","bot":{"userAgent":"GPTBot/1.1","source":"manual-test"}}'

Expect 202 with tracked: true. Then check your dashboard's Bot traffic card for the new entry — it should land within a few seconds.

Where to find the data

Open your dashboard and look for the Bot traffic card. Switch between AI Answers, Indexing, and Training tabs, see the timeline for the selected category, and check the provider breakdown on the side for exact counts per vendor.

Track social mentions on your analytics chart

See when your brand is mentioned on X directly on your main analytics chart — no more guessing whether a traffic spike came from social media or somewhere else.

Requires a Convrs Growth plan.

Why track mentions?

Knowing when — and where — people are talking about your product helps you:

  • Connect social buzz to revenue — see which mentions actually turned into traffic and sales, not just noise.
  • Catch viral moments early — spot a spike in mentions while it's happening, not two days later when you check analytics.
  • Time your launches — ship a campaign when conversation about your brand is already warm.

How it works

When someone mentions one of your tracked keywords on X, Convrs picks it up automatically and overlays it on your main analytics chart as social activity.

Hovering a day with activity shows:

  • The author's avatar, stacked alongside anyone else who mentioned you that day
  • A short preview of the post content, right in the chart tooltip
  • How that day's mentions line up against your visitor and revenue numbers

If there's more activity than fits in the tooltip preview, a View all button opens the full list for that day — every mention, with the full post content, author, and a link out to the original post.

X mentions

Convrs searches X for your tracked keywords and your domain, and surfaces any tweet that mentions your brand.

Set up mention tracking

  1. Go to Settings → Integrations.
  2. Find the Twitter / X card.
  3. Click the Mentions tab.
  4. Add the keywords you want tracked.

Keyword rules

  • 4–15 characters per keyword
  • Matching is case-insensitive
  • Include the @ symbol to track handle mentions (e.g. @convrsdev)
  • Avoid generic single words — they'll mostly surface noise, not signal

Your workspace's domain is tracked automatically — you don't need to add it as a keyword yourself.

A note on connection status

The Twitter / X card shows whether your workspace currently has an active X connection. You can still add keywords and link-attribution accounts before connecting — they'll just sit ready and start surfacing mentions as soon as the connection is active.

Best practices

  • Track your brand and product names — the highest-signal keywords you can add.
  • Track campaign hashtags — add a hashtag right when a campaign launches so you catch the conversation from day one.
  • Skip generic terms — words like "analytics" or "software" will flood your mention feed with unrelated noise.

Go further

Mentions tell you that people are talking about you. Pair this with X link attribution to see exactly which tweets are turning that conversation into visitors and revenue.

Stripe Revenue Attribution

Connect Stripe with Convrs to attribute revenue back to the campaigns, traffic sources, and visitors that generated it.

Once connected, Convrs automatically links successful payments to the original visitor and session, allowing you to see which channels, campaigns, and pages generate revenue.

How It Works

  1. A visitor lands on your website.
  2. Convrs assigns a unique visitor and session ID.
  3. You pass those IDs to Stripe when creating a checkout session or payment intent.
  4. Stripe sends the payment data to Convrs.
  5. Convrs attributes revenue to the original visitor, campaign, and traffic source.

Required Metadata

When creating a payment, include the following metadata:

KeyDescription
convrs_visitor_idUnique visitor identifier assigned by Convrs.
convrs_session_idSession identifier assigned by Convrs.

These values allow Convrs to connect a Stripe payment to the visitor who originally started the journey.

Stripe Checkout

If you're using Stripe Checkout, include the Convrs identifiers in the checkout session metadata.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const session = await stripe.checkout.sessions.create({
  line_items: [
    {
      price: "price_123",
      quantity: 1,
    },
  ],

  mode: "payment",

  success_url: "https://yourapp.com/success",
  cancel_url: "https://yourapp.com/cancel",

  metadata: {
    convrs_visitor_id: visitorId,
    convrs_session_id: sessionId,
  },
});

Payment Intents

For custom checkout flows, pass the identifiers when creating the payment intent.

1
2
3
4
5
6
7
8
9
10
const paymentIntent =
  await stripe.paymentIntents.create({
    amount: 5000,
    currency: "usd",

    metadata: {
      convrs_visitor_id: visitorId,
      convrs_session_id: sessionId,
    },
  });

Getting Visitor Information

If you're using the Convrs SDK, retrieve the tracking identifiers before creating the checkout session.

1
2
3
4
const tracking =
  convrs.getTrackingParams();

console.log(tracking);

Example response:

1
2
3
4
{
  visitorId: "visitor_123",
  sessionId: "session_456"
}
1
2
3
4
5
6
7
8
9
10
11
Visitor arrives
       ↓
Convrs creates visitor + session
       ↓
User starts checkout
       ↓
Pass IDs to Stripe metadata
       ↓
Payment succeeds
       ↓
Revenue appears in Convrs

Verify Revenue Attribution

After a successful payment, open your Convrs dashboard and navigate to:

Revenue Attribution → Payments

You should see:

  • Revenue amount
  • Customer information
  • Original traffic source
  • Campaign attribution
  • Landing page
  • Visitor journey

Revenue attribution works for one-time payments, subscriptions, upgrades, and renewals as long as the Convrs identifiers are included in the Stripe metadata.