Sign in

Installation

Add your site in the dashboard and copy the snippet with your ID. Here are the steps for each framework.

HTML

Paste the snippet inside the <head> of every page.

<script
  defer
  data-site="st_YOUR_ID"
  src="https://in.datatrack.dev/js/script.js">
</script>

Next.js

File: app/layout.tsx. In the App Router root layout, using next/script. It loads once and detects client-side navigations.

import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          data-site="st_YOUR_ID"
          src="https://in.datatrack.dev/js/script.js"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

Astro

File: src/layouts/Layout.astro. In your base layout, inside the <head>. is:inline stops Astro from processing and bundling it. If you use View Transitions, the script detects page changes.

<head>
  <script
    is:inline
    defer
    data-site="st_YOUR_ID"
    src="https://in.datatrack.dev/js/script.js">
  </script>
</head>

WordPress

File: functions.php (child theme). Add it to your child theme's functions.php, or paste the HTML snippet into the header with a plugin like WPCode.

add_action('wp_head', function () {
  echo '<script defer data-site="st_YOUR_ID" src="https://in.datatrack.dev/js/script.js"></script>';
});

Shopify

File: layout/theme.liquid. In Online Store → Themes → Edit code, inside the <head> of theme.liquid.

<script
  defer
  data-site="st_YOUR_ID"
  src="https://in.datatrack.dev/js/script.js">
</script>

Nuxt

File: nuxt.config.ts. Add it as a global app script.

export default defineNuxtConfig({
  app: {
    head: {
      script: [{ src: "https://in.datatrack.dev/js/script.js", defer: true, "data-site": "st_YOUR_ID" }],
    },
  },
});

Your own subdomain (recommended)

Ad blockers stop requests to analytics domains, so 10–30% of visits never arrive. In your website's settings, add a subdomain such as m.yoursite.com and create the CNAME record it shows you. Once it's active, load the script from it:

<script defer data-site="st_YOUR_ID" src="https://m.yoursite.com/js/script.js"></script>

It works with any DNS provider. Only the address changes: the data collected and the cookieless mode stay the same. Pick a neutral name (m., e., data.); names like analytics. or stats. are on blocklists.

AI and search bots

ChatGPT, Claude, Perplexity or Google read your pages without running JavaScript, so the script never sees them. Your server can report them in the background. Only known bots are recorded, and visitors aren't affected.

Cloudflare Pages: functions/_middleware.ts

const BOTS = /bot|crawl|spider|chatgpt|claude|perplexity|anthropic|bytespider|meta-external/i;

export const onRequest: PagesFunction = async ({ request, next, waitUntil }) => {
  const ua = request.headers.get("user-agent") ?? "";
  const page = !/\.[a-z0-9]{2,5}$/i.test(new URL(request.url).pathname); // pages, not files
  if (request.method === "GET" && page && BOTS.test(ua)) {
    waitUntil(fetch("https://in.datatrack.dev/crawler", {
      method: "POST",
      body: JSON.stringify({ s: "st_YOUR_ID", u: request.url, ua }),
    }));
  }
  return next();
};

Next.js: middleware.ts

import { NextResponse, type NextFetchEvent, type NextRequest } from "next/server";

const BOTS = /bot|crawl|spider|chatgpt|claude|perplexity|anthropic|bytespider|meta-external/i;

export function middleware(req: NextRequest, event: NextFetchEvent) {
  const ua = req.headers.get("user-agent") ?? "";
  if (BOTS.test(ua)) {
    event.waitUntil(fetch("https://in.datatrack.dev/crawler", {
      method: "POST",
      body: JSON.stringify({ s: "st_YOUR_ID", u: req.url, ua }),
    }));
  }
  return NextResponse.next();
}

export const config = { matcher: ["/((?!_next|.*\\..*).*)"] };

Custom events

window.datatrack?.track("signup", { plan: "pro" });

Or mark any element and the click is sent as that event, no code needed:

<a href="/pricing" data-dt-event="pricing_cta" data-dt-value="29">See plans</a>

Server events

What happens in your backend (a payment, a confirmed sign-up, a qualified lead) can be sent with an API key from Settings → API. It shows under Events and counts as a goal of type "Server event", like anything the script sends.

curl -X POST https://in.datatrack.dev/v1/events \
  -H "Authorization: Bearer dt_live_…" \
  -H "Content-Type: application/json" \
  -d '{"site":"st_…","name":"payment_completed","value":49,"visitor":"<dt_vid or your user id>","props":{"plan":"pro"}}'

One event or an array of up to 100 per request; the whole request is accepted (202) or rejected with the reason (400). site andname are required. visitor ties the event to a person: the id the script keeps in dt_vid (full mode) or your own user id; without it each event counts as one visitor. url must be on the website's domain. Limits: 600 events a minute per key, 64 KB per request.

Scroll, downloads, forms

Always on: how far each visit scrolls (sent with the engagement time) and clicks on downloads (download, with the file name),mailto: (email_click) and tel: (phone_click) links. Opt in with attributes on the script:

<script defer data-site="st_…" data-forms data-rage data-clicks src="https://in.datatrack.dev/js/script.js"></script>

Also always on, from your markup:

All of them are events: add a goal of type "Event" with the name to count them, or use them in funnels.

Email campaigns

Measure the emails you send yourself (newsletters, transactional mail) next to the visits they bring. Pick a campaign name (letters, digits, dots, dashes) and add two things to the email. Nothing identifies the recipient.

An open pixel, at the end of the HTML:

<img src="https://in.datatrack.dev/px/st_…/newsletter-nov.gif" width="1" height="1" alt="">

And each link through the redirect, with the destination URL-encoded in u. Only links to your own domain are allowed; the visit arrives with utm_campaign set, so it shows under the Email channel:

https://in.datatrack.dev/r/st_…/newsletter-nov?u=https%3A%2F%2Fyoursite.com%2Foffers

If the website has its own subdomain set up, use it instead of in.datatrack.dev. Apple Mail and Gmail preload images, so opens run high: clicks and visitors are the reliable numbers.