One script tag before </body>, one attribute with your site code. Two minutes later you can watch yourself walk through your own site in the realtime view.
Paste this just before the closing </body> tag on every page you want to track.
<script>
(function(){
var s=document.createElement('script');
s.src='https://www.corbacount.com/tracker.js';
s.async=true;s.dataset.site='YOUR_SITE_CODE';
document.head.appendChild(s);
})();
</script>
This is exactly the snippet the dashboard's copy button gives you under Sites - Tracking code, with your real site code filled in. Three things matter here, and the tracker is strict about all of them:
data-site attribute on the injected script tag; the tracker scans the page for a script tag that has tracker.js in its src and a data-site attribute. If the attribute is missing it does nothing, silently. The value is the 32-character site code from the dashboard.src URL, so a self-hosted copy of the file would beacon into the void. Keep the src as the dashboard gives it to you.async keeps your page fast. The browser downloads and runs the tracker without ever blocking HTML parsing or rendering.
Prefer a plain tag? <script async src="https://www.corbacount.com/tracker.js" data-site="YOUR_SITE_CODE"></script> does exactly the same thing - both forms are correct, pick whichever fits your templates.
Optional: add s.dataset.version='1.2.0' to the snippet (or set window.corbacount_version before the tracker loads - the attribute wins, and the value is capped at 100 characters) to slice your analytics by deploy version. The dashboard's version-tracking section hands you that variant ready to copy.
No magic, no queueing library, no third-party requests. One small script, one beacon.
The tracker collects the page URL, referrer, title, screen size, browser language and any utm_* parameters, then sends a single JSON POST to /api/track using navigator.sendBeacon. Old browsers fall back to a 1x1 image request. Your page never waits for our server - the server's whole reply is an empty 204.
On a first visit the tracker sets _cc_vid - a random UUID stored as a first-party cookie on your own domain for 365 days, SameSite=Lax. It exists purely so we can tell new visitors from returning ones. It never follows anyone to another site.
The script quietly observes LCP, INP and CLS while the visitor browses and sends one extra beacon to /api/vitals when they leave the page. That is how the Core Web Vitals report shows field data instead of lab guesses.
The whole tracker is wrapped in a try/catch and fails silently. The file is 7.3 KB raw and 2.2 KB gzipped over the wire - we measured the exact file we serve, not a marketing number.
You do not need to wait a day for data. You are the test traffic.
Add it to your footer template so it ships on every page, then deploy. If you use a caching layer or CDN, purge it once so the new HTML actually reaches browsers.
Open your site in a normal browser tab and click through a few pages. No incognito tricks needed - your visits count like anyone else's.
Open Real-time in the dashboard. Within seconds you should see yourself appear - country, browser, current page - pushed live, no refresh. Note that known bots are filtered out, so a curl request will not show up.
Pageviews flow in on their own. Conversions need you to say what counts. There are two ways - the goals & funnels page covers what you can do with them once they exist.
Create a goal in the dashboard with a URL pattern like /thanks or /order/*/complete (the * wildcard is supported, matching is case-insensitive). Every pageview is checked against it server-side. Counting starts the moment you create the goal.
For conversions without a dedicated URL - AJAX forms, in-app events, single-page flows. Create a goal of type JavaScript trigger in the dashboard, then call window.corbacount_goal() from your code.
// after a successful signup, for example in your AJAX callback:
if (typeof window.corbacount_goal === 'function') {
window.corbacount_goal('signup');
}
// optional second argument: a dedup reference such as an order id.
// the same ref is counted only once for this goal, so a server-side
// webhook firing the same goal later will not double-count it.
window.corbacount_goal('purchase', order_id);
The function only exists once tracker.js has loaded - it loads async, so keep the typeof guard if your code can run early. There is also a server-side goal API for webhooks and background jobs, authenticated with a secret key; you will find it ready to copy under Sites - Tracking code in the dashboard.
Honest answer: the tracker records one pageview per full page load. It does not hook history.pushState yet, so client-side route changes in React, Vue or similar SPAs are not tracked automatically - you will see the entry page but not the in-app navigation. JavaScript goals via corbacount_goal() work fine anywhere in an SPA, so conversions are still covered. Automatic SPA route tracking is on the roadmap; if it is a blocker for you, tell us and we will bump it.
No. The script is 2.2 KB gzipped, loads with async so it never blocks rendering, and reports with sendBeacon so your page never waits for our server. If our infrastructure went down entirely, your site would not notice - the tracker fails silently by design.
Corbacount sets one first-party cookie, _cc_vid, used only to recognise returning visitors to your own site. There is no cross-site tracking and no advertising profile. Whether that still requires consent depends on your jurisdiction - we wrote an honest breakdown in our cookie banner guide.
Yes. The tracker coexists fine with GA4, Tag Manager, Plausible or Matomo. A common path is running both for a month, comparing, then removing the one you no longer need. Expect our counts to be higher - we also count the ad-block users GA misses.
Every plan starts with a 14-day free trial, no credit card. Drop your email and we will let you know when it is your turn.