Hosting · 2 min setup
How to add analytics to a Netlify site
</head>, and save. Netlify injects it as pages are served; for routes rendered by functions, add the tag in your framework instead.Updated
Snippet injection rewrites static HTML on its way out, which makes it ideal for static sites and site generators — no rebuild, no commit. It doesn't apply to proxied routes or responses generated by Netlify Functions, so server-rendered pages (SSR Next.js, Astro, Remix and similar on Netlify) need the tag in the framework's layout instead.
Netlify at a glance
- No-code option
- Post processing → Snippet injection → before
</head> - Doesn't cover
- Function-rendered (SSR) and proxied routes
- Deploy previews
- Dropped once you save Allowed hostnames
- CSP
_headersfile or[[headers]]innetlify.toml- Netlify Forms
- Thank-you page → page goal
How to install VisitTrack on Netlify
Step 1: Copy your site id
Add your Netlify site's domain in VisitTrack and copy the snippet from the install step. Replace
SITE_IDbelow.Step 2: Open Snippet injection
In the Netlify UI, open your project → Project configuration → Build & deploy → Post processing → Snippet injection, and click Add snippet. (Netlify occasionally moves this page; search the project configuration for "Snippet injection".)
Step 3: Insert the tag before </head>
Choose to insert before
</head>, name it "VisitTrack", paste the tag and save. It applies to pages served from then on, without a redeploy.Snippet injection → before </head><script defer data-site="SITE_ID" src="https://visitrack.app/tracker.js"></script>Step 5: Keep deploy previews out
Deploy previews and branch deploys live on URLs like
deploy-preview-12--yoursite.netlify.app. Save your production domain under VisitTrack's Settings → General → Allowed hostnames and those hits are dropped.
How to check VisitTrack is working on Netlify
- Open the production site and view source — the tag sits right before
</head>. - Browse two pages; VisitTrack's live view shows you, and the Pages tab lists both paths.
- Open an SSR route too: if its source has no tag, that route is function-rendered and needs the in-code install.
Does VisitTrack track Netlify page navigation?
Netlify serves your build output; navigation tracking depends on your site. Static pages count one pageview per load, and client-side routers (React, Vue, SvelteKit, Gatsby, Docusaurus) are followed through the History API. Netlify redirects and rewrites happen before the page loads, so the path recorded is the one in the browser's address bar.
How to track custom events and goals in Netlify
Netlify Forms are standard HTML forms (<form data-netlify="true">), so with automatic events on, each submission records a form_submit event. For a clean conversion, give the form an action pointing at a thank-you page and create a page goal for that exact path in Settings → Goals.
<form name="contact" method="POST" data-netlify="true" action="/thanks/">
<input type="hidden" name="form-name" value="contact" />
<input name="email" type="email" required />
<button data-vt-goal="contact_submit_click">Send</button>
</form>Anywhere else, data-vt-goal on an element or window.visitrack("name") in your own JavaScript records custom events.
Allow VisitTrack in Netlify headers
If you set a Content-Security-Policy in a _headers file (in your publish directory) or netlify.toml, add the VisitTrack origin to script-src and connect-src, merged into your existing policy.
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = "default-src 'self'; script-src 'self' https://visitrack.app; connect-src 'self' https://visitrack.app;"Track AI crawlers on Netlify
For a static site, the edge is the only layer that sees crawler requests. A Netlify Edge Function can report each request to VisitTrack without delaying the response; it runs on every path, including robots.txt and sitemap.xml. Background: AI crawler tracking.
// netlify/edge-functions/visitrack-crawlers.js
export default async (request, context) => {
const url = new URL(request.url);
context.waitUntil(
fetch("https://visitrack.app/api/collect-bot", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
siteId: "SITE_ID",
path: url.pathname,
userAgent: request.headers.get("user-agent"),
ip: context.ip,
}),
}).catch(() => {}),
);
return context.next();
};
export const config = { path: "/*" };Script options you might need on Netlify
All optional — add them to the same tag. Full reference: script configuration.
| Attribute | What it does |
|---|---|
data-cookieless | Store nothing in the browser; the server derives a daily-rotating id. See cookieless mode. |
data-exclude="/app/*" | Never track these paths (comma-separated, * wildcard). Checked on every navigation. |
data-allow-local | Track on localhost and *.local — for testing an install only. |
data-debug | Log every event the script sends, and why it skipped one, to the console. |
data-auto="false" | Turn off automatic events (downloads, contact clicks, form submits, rage clicks, JS errors, 404s). |
Netlify troubleshooting
The snippet isn't on some pages
Those routes are rendered by functions or proxied, which Snippet injection doesn't touch. Add the tag in the framework layout and remove the snippet.
Pageviews doubled
The tag is injected by Netlify and also present in your HTML. Keep one.
Deploy previews in your numbers
Save your production domain in Allowed hostnames in VisitTrack.
CSP violation for visitrack.app
Add the origin to both script-src and connect-src in _headers or netlify.toml, then redeploy (headers are deployed with the site).
Netlify analytics FAQ
How do I add analytics to a Netlify site without code?
Use Snippet injection in Project configuration → Build & deploy → Post processing: insert the VisitTrack tag before </head>. Netlify adds it to static pages as they're served, without a redeploy.
Why doesn't Netlify Snippet injection work on my SSR pages?
Snippet injection only rewrites static HTML. Pages rendered by Netlify Functions or proxied to another origin aren't processed, so add the tag in your framework's layout for those.
How do I keep Netlify deploy previews out of my analytics?
Save your production domain under Settings → General → Allowed hostnames in VisitTrack; hits from deploy-preview and branch-deploy hostnames are then dropped.
Can I track Netlify Forms submissions?
Yes. Automatic events record a form_submit event for each submission, and a thank-you page plus a page goal gives you a clean conversion count by source.
Does VisitTrack replace Netlify's own analytics?
It answers different questions: VisitTrack runs in the browser and adds UTM campaigns, custom events, funnels, revenue attribution and session replays, without cookies in cookieless mode.
Keep going
- Vercel analyticsUse VisitTrack on Vercel: add the tag in your framework, keep preview deployments out with VERCEL_ENV or allowed hostnames, and set CSP headers.
- Cloudflare Pages analyticsAdd VisitTrack on Cloudflare Pages in your HTML or with an HTMLRewriter middleware, exclude it from Rocket Loader, and track AI crawlers at the edge.
- Hugo analyticsAdd VisitTrack to a Hugo site through your theme's head partial, loaded only in production with hugo.IsProduction, plus a shortcode for goals.
- Gatsby analyticsAdd VisitTrack to Gatsby with setHeadComponents in gatsby-ssr — rendered into every page's head, with Gatsby Link navigations tracked automatically.
- Install the tracking scriptThe reference tag, CSP notes and how to check it's working.
- Custom events and signupsvisitrack(), data-vt-goal, scroll events and server-side signups.
- Use casesHow SaaS teams, indie hackers, stores and agencies use VisitTrack.
- VisitTrack vs Google AnalyticsCookie-free analytics with revenue attribution, compared honestly.
Add VisitTrack to your Netlify site
Cookie-free analytics with revenue attribution, live visitors, funnels and session replays. One script tag, every feature on every plan. 14 days free, no card required.
Not on Netlify? See all 29 integration guides.