@antlytics/analytics
Privacy-first analytics SDK for Next.js and vanilla JS.
- No cookies set
- Session ID stored in
sessionStorageonly — cleared when the tab closes - UTM parameters read automatically from the page URL
- Lightweight inline script — no extra network round-trip
Installation
npm install @antlytics/analytics
# or
pnpm add @antlytics/analytics
Next.js App Router
Drop the <Analytics /> component into your root layout. It renders an
inline script via next/script (strategy="afterInteractive") so it does
not block the initial render.
// app/layout.tsx
import { Analytics } from "@antlytics/analytics/next"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
<Analytics trackingId="YOUR_TRACKING_ID" />
</html>
)
}
Your tracking ID is in the Antlytics dashboard under Settings → Getting Started.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
trackingId |
string |
— | UUID tracking ID from your Antlytics dashboard |
apiHost |
string |
https://www.antlytics.com |
Override if you use a first-party proxy |
First-party proxy (optional)
Some ad blockers block requests to third-party analytics domains. Route pageview events through your own domain to bypass most blockers.
1. Create the proxy route in your Next.js app:
// app/api/antlytics/pageview/route.ts
export { GET, OPTIONS, POST } from "@antlytics/analytics/proxy"
2. Point <Analytics /> at your own domain:
<Analytics
trackingId="YOUR_TRACKING_ID"
apiHost="https://your-domain.com"
/>
The proxy forwards POST /api/antlytics/pageview → https://www.antlytics.com/api/ingest/pageview
(plus the browser User-Agent and client IP via X-Antlytics-Client-Ip) and always returns 200
to the tracker, so proxy failures are silent.
Vanilla snippet
For non-Next.js sites, paste this snippet into every page's <head>:
<script>
(function(){
var t="YOUR_TRACKING_ID",
u="https://www.antlytics.com/api/ingest/pageview",
k="ant_sid";
function sid(){
try{var s=sessionStorage.getItem(k);if(s)return s;s=crypto.randomUUID();sessionStorage.setItem(k,s);return s;}
catch(e){return crypto.randomUUID();}
}
function utm(){
try{var p=new URLSearchParams(location.search),o={};
["utm_source","utm_medium","utm_campaign","utm_term","utm_content"].forEach(function(k){var v=p.get(k);if(v)o[k]=v;});
return o;}catch(e){return {};}
}
function send(){
fetch(u,{method:"POST",headers:{"Content-Type":"application/json"},keepalive:true,
body:JSON.stringify(Object.assign({tracking_id:t,pathname:location.pathname,referrer:document.referrer||undefined,session_id:sid()},utm()))});
}
send();
window.addEventListener("popstate",send);
})();
</script>
Ingest API
The endpoint is POST https://www.antlytics.com/api/ingest/pageview.
| Field | Type | Required | Description |
|---|---|---|---|
tracking_id |
UUID | yes | Your site's tracking ID |
pathname |
string | yes | URL path, e.g. /blog/post |
referrer |
string | no | Full referrer URL |
session_id |
UUID | no | Anonymous session identifier |
utm_source |
string | no | Campaign source |
utm_medium |
string | no | Campaign medium |
utm_campaign |
string | no | Campaign name |
utm_term |
string | no | Paid search keyword |
utm_content |
string | no | Ad/link differentiator |
Country and device type are detected server-side from request headers — you do not need to send them.
License
MIT Antlytics