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.
Copy and paste this code 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>
Paste it just before the closing </body> tag on every page you want to track. 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:
The loader sets it as the 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.
The tracker derives its reporting endpoint from its own 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 fastThe browser downloads and runs the tracker without ever blocking HTML parsing or rendering.
Does exactly the same thing - pick whichever fits your templates
<script async src="https://www.corbacount.com/tracker.js" data-site="YOUR_SITE_CODE"></script>
Slice your analytics by release
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. 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 whole tracker is wrapped in a try/catch and fails silently, so it can never break your page.
On a first visit it sets _cc_vid - a random UUID on your own domain for 365 days, SameSite=Lax. It exists purely to tell new visitors from returning ones and never follows anyone to another site.
Page URL, referrer, title, screen size, browser language and any utm_* parameters go out as a single JSON POST to /api/t via navigator.sendBeacon. Old browsers fall back to a 1x1 image request. The server's whole reply is an empty 204.
LCP, INP and CLS are observed while the visitor browses and sent in 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.
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. 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.
Zero code
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.
One call
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.
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.
// 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);
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 about 3.3 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.