One script tag. Zero cookies. No build step. Works with every framework — static HTML, React, Next.js, Vue, or anything in between.
Three steps to go from zero to live analytics.
Sign in, navigate to Websites, and add your domain. NeuTarget generates a unique Website ID for you.
Your Website ID
e.g. a1b2c3d4-e5f6-7890-abcd-ef1234567890
Add this single script tag before the closing </head> of your website. Replace YOUR_WEBSITE_ID with the ID from Step 1.
<!-- NeuTarget Analytics · < 1 KB · Cookie-free -->
<script
defer
data-website-id="YOUR_WEBSITE_ID"
src="https://www.neutarget.com/js/tracker.js"
></script>Push your changes live. The tracker automatically fires a pageview event on load.
Open your site in a browser and visit any page.
Return to your NeuTarget dashboard — the Overview page will show the visit within seconds.
Done. No configuration files, no build plugins, no ENV vars.
The tracker script works universally, but here's where to place it in popular frameworks.
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<script
defer
data-website-id="YOUR_WEBSITE_ID"
src="https://www.neutarget.com/js/tracker.js"
/>
</head>
<body>{children}</body>
</html>
);
}SPA navigations are tracked automatically via MutationObserver + popstate. No router.events hookup required.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script
defer
data-website-id="YOUR_WEBSITE_ID"
src="https://www.neutarget.com/js/tracker.js"
></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>export default defineNuxtConfig({
app: {
head: {
script: [
{
defer: true,
src: "https://www.neutarget.com/js/tracker.js",
"data-website-id": "YOUR_WEBSITE_ID",
},
],
},
},
});<head><script
defer
data-website-id="YOUR_WEBSITE_ID"
src="https://www.neutarget.com/js/tracker.js"
></script>For WordPress, paste this in Appearance → Theme Editor → header.phpor use a “Insert Headers & Footers” plugin.
Confirm the tracker is installed correctly and data is flowing.
track./api/v1/track with a 200 or 204 status.websiteId, eventType: "pageview", pathname, etc.{
"websiteId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"eventType": "pageview",
"pathname": "/",
"referrer": "",
"deviceType": "DESKTOP",
"loadTimeMs": 342,
"utmSource": "google",
"utmMedium": "cpc",
"utmCampaign": "spring-sale"
}Visit your site in a browser, then check the Overview page in your NeuTarget dashboard. Within seconds you should see:
Send a test event directly from your terminal to confirm the backend is reachable:
curl -X POST https://www.neutarget.com/api/v1/track \
-H "Content-Type: application/json" \
-d '{
"websiteId": "YOUR_WEBSITE_ID",
"eventType": "pageview",
"pathname": "/test",
"referrer": "",
"deviceType": "DESKTOP",
"loadTimeMs": 200
}'A 200 OK or 204 No Content response confirms NeuTarget is receiving your events.
The tracker script automatically captures these events — zero configuration required.
Fired on every page load and SPA route change. Includes pathname, referrer, device type, load time, and UTM params.
Fired when a visitor clicks a link to Razorpay, PhonePe, Instamojo, or a upi: URI. Captures the target URL.
Fired when a visitor clicks a link to Google Play Store or Apple App Store. Captures the target URL.
Fired on uncaught JavaScript errors and unhandled promise rejections. Capped at 5 per page session to avoid noise.
Every event sends a JSON payload with these fields.
| Field | Type | Description |
|---|---|---|
websiteId | string (UUID) | Your website's unique identifier from the dashboard |
eventType | string | "pageview" | "payment_click" | "appstore_tap" |
pathname | string | Current URL path, e.g. /pricing |
referrer | string | document.referrer — the page that linked here |
deviceType | string | "MOBILE" | "TABLET" | "DESKTOP" |
loadTimeMs | number | null | Page load time in ms (pageview events only, first load) |
targetUrl | string | Outbound link URL (payment_click & appstore_tap only) |
utmSource | string | undefined | UTM source param, captured from the landing page URL and persisted for the session |
utmMedium | string | undefined | UTM medium param, captured from the landing page URL and persisted for the session |
utmCampaign | string | undefined | UTM campaign param, captured from the landing page URL and persisted for the session |
errorDetails | string (JSON) | Serialized error info — message, source file, line, column (js_error events only) |
Configure the tracker via HTML attributes on the <script> tag.
| Attribute | Required | Description |
|---|---|---|
data-website-id | Required | The UUID of the website you registered in the dashboard. |
defer | Recommended | Ensures the script doesn't block page rendering. Always include this. |
A brief look under the hood for the curious engineer.
Unique visitors are identified by a daily-rotating cryptographic hash of the visitor's IP + User-Agent + a salt. The hash changes every 24 hours, so no persistent tracking is possible. Zero cookies set, ever.
Events are sent via navigator.sendBeacon() for reliability (survives page unload). Falls back to fetch({ keepalive: true }) on older browsers.
A MutationObserver watches for DOM changes, combined with a popstate listener. When the URL path changes, a new pageview is fired — no router integration needed.
A single global click event listener uses element.closest("a")to detect payment & app-store outbound links, no matter how deeply nested the click target is.
Common issues and their fixes.
I don't see any Network requests to /api/v1/track
Confirm the <script> tag is inside <head>, has the "defer" attribute, and the data-website-id is set. Also check that the src URL is correct and the script loads (200 status in the Network tab).
I see a CORS error in the console
If you've set up a custom tracking domain, replace the script src with your domain URL. Otherwise, use the default https://www.neutarget.com/js/tracker.js — it works out of the box.
SPA route changes aren't being tracked
The MutationObserver requires document.body to exist when the script runs. Make sure the script tag is deferred (not async) and placed in <head>. If using a framework with aggressive tree-shaking, confirm tracker.js is not being removed.
Payment / App Store clicks aren't showing up
The tracker looks for <a> tags with href containing razorpay.com, phonepe.com, instamojo.com, upi:, play.google.com, or apps.apple.com. Ensure your links use standard <a> elements (not JavaScript onclick handlers without an href).
Load time shows as null
loadTimeMs is only captured on the initial full-page load (not SPA navigations). It uses the Performance API — if the page hasn't fully loaded when the event fires (e.g. very fast prerender), it may be null.
Create a free account, add your domain, and paste the snippet. You'll see live data in under 2 minutes.
Get Started Free