Penny Metrics is a lightweight, privacy-friendly, cookie-free web analytics tool. Drop one small script onto your site and watch visitors, pageviews, referrers, and custom events roll in — no consent banner required.
Async, deferred, and never blocks rendering.
Daily-rotating visitor hashes — GDPR friendly.
Track clicks and conversions with one attribute.
-
Add your site
Sign in, open the Dashboard, and click "Add site". Enter the domain you want to track (for example, mydomain.com).
-
Install the snippet
Copy the snippet from your site's menu and paste it inside the <head> of every page you want to track. It is the same snippet shown here, with your domain filled in:
html
<script defer src="https://pennymetrics.dev/stats.js" data-hostname="mydomain.com" ></script> -
Watch the data arrive
Deploy your change and visit your site. Within a few seconds the first pageview appears on your analytics dashboard. That's it!
Configure the tracker with data attributes on the script tag.
|
Attribute
|
Required
|
Description
|
|---|---|---|
data-hostname
|
No | The domain to attribute traffic to. Defaults to the current window hostname. Set this when serving the same code from multiple domains or from localhost. |
data-debug
|
No | Logs every payload to the browser console instead of sending silently. Handy while verifying your install locally. |
Track conversions like sign-ups, purchases, or downloads. There are two ways to send an event.
Add data-s-event to any element. The event is sent automatically when the element is clicked.
html
<button data-s-event="Signup click">Sign up</button>
Attach extra properties with data-s-event-props. Separate pairs with a semicolon and keys from values with an equals sign:
html
<button
data-s-event="Signup click"
data-s-event-props="plan=pro;period=monthly"
>
Sign up
</button>
Call window.stats.event() for anything that isn't a simple click. The signature is event(name, path?, props?):
javascript
window.stats.event("Signup click", "/dashboard/[userId]/settings", {
plan: "pro",
logged_in: "true",
});
The tracker hooks into the History API, so client-side navigations (pushState / replaceState / back & forward) are counted as pageviews automatically. React Router, Vue Router, Livewire wire:navigate, and similar libraries work out of the box.
If you navigate in some other way and need to record a pageview manually, call:
javascript
window.stats.pageview();
The tracker is designed to be compliant by default:
No cookies or other persistent identifiers are stored on visitors' devices.
Visitors are counted using a hash of a daily-rotating salt, the site, the IP address, and the user agent. Raw IP addresses are never stored.
Because the salt rotates every day, visitors cannot be tracked across days, and the hash cannot be reversed.
Known bots and crawlers are detected and discarded.
Under the hood the script sends a POST request to the ingest endpoint with a JSON body. You normally never need this, but it is documented here for custom integrations.
bash
curl -X POST https://pennymetrics.dev/api/collect \
-H "Content-Type: text/plain" \
-d '{
"type": "pageview",
"hostname": "mydomain.com",
"path": "/pricing",
"query": "?utm_source=newsletter",
"referrer": "https://news.ycombinator.com/"
}'
|
Field
|
Type
|
Description
|
|---|---|---|
type
|
Either "pageview" or "event". | |
name
|
Event name. Required when type is "event". | |
hostname
|
The domain the hit belongs to. Must match a registered site. | |
path
|
The page path, e.g. /pricing. | |
query
|
The query string. UTM parameters are parsed from it. | |
referrer
|
The full referring URL. Self-referrals are dropped. | |
props
|
Optional key/value pairs of scalar values (events only). |
Add the data-debug attribute to the script and reload the page. You should see the payload logged in the console. Confirm the data-hostname exactly matches the domain you registered, and that the snippet is in the <head>.
Set data-hostname to your real registered domain while testing locally, otherwise hits are attributed to "localhost" and dropped as an unknown site.
Use an ad blocker or a browser extension that blocks the script, or simply browse with the tracker disabled during development.
Still stuck? Open the Dashboard to manage your sites.