Documentation

NeatStats offers simple, lightweight, privacy-first web stats. This page covers everything there is to know about the service.

Privacy

We count views, not people. We don’t store IP addresses, we don’t use cookies, and we don’t track individuals or their behavior.

NeatStats focuses on privacy by counting views, not tracking viewers. We don’t do any fingerprinting, nor do we perform any behavioral tracking of any kind. Our pageview counter doesn’t set any cookies or use any browser local storage.

We only store the most basic information about the page view: the URL of the page, the referrer (if the browser provides one), the user agent header, and the GeoName. GeoNames are coarse indicators of location, usually aligned with the center of the nearest city. NeatStats doesn’t collect or store precise location information—only GeoNames.

Here’s a sample database entry, so you can see the data that we store:

Item Sample How it’s used
URL https://neatstats.net/ This is the URL of the page that was viewed.
Referrer https://social.lol/ This is the URL where the link was clicked to view the page.
GeoName ID 4299276 This is the GeoName ID representing the rough location from which the page was viewed. These are coarse representations of location, generally tied to nearby city-centers. (This one is Louisville, Kentucky, USA.)
User Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15 This is the User Agent header, which provides information about the web browser. (This one is Safari running on macOS.)
Timestamp 1768837753 This is the UNIX timestamp of the page view. (This one is “Mon, 19 Jan 2026 15:49:13 GMT”.)

NeatStats members can see which of their web pages were viewed, how often they were viewed, and by what web browsers. They can also view a map showing the GeoNames from which their pages were viewed.

NeatStats does not store any information about individual people, and no attempt is made to identify people through any of the data collected.

How the view counter works

The view counter is a tiny script that runs once when a page loads. It doesn’t hide what it is, and it doesn’t pretend to be something else. It doesn’t use a tracking pixel, it isn’t disguised as part of your site, and it doesn’t load anything else. It sends one small message straight to neatstats.net, and that’s it. You can see the whole thing at https://neatstats.net/view.js.

Here’s what happens when the script is loaded:

Getting started

Setting up NeatStats only takes a few minutes. Here’s how it works:

  1. Sign in with your Neatnik ID.
  2. Add your site on the Your sites page. Just type in its domain, like example.com.
  3. Verify that it’s yours. We give you three ways to do this, so pick whichever is easiest for you (a DNS TXT record, a small file at /.well-known/neatstats, or a meta tag on your home page). Once you’ve added one, click the button to check it.
  4. Add the view counter to any page you want to count. Paste this into your HTML (near the end of the page is great):
<script src="https://neatstats.net/view.js"></script>

That’s it! Views will start showing up on your site’s stats page within a few seconds.

Each domain is its own site. If people visit both example.com and www.example.com, add both so you can see the views for each. If they’re really the same site, you can combine them.

The view counter is tiny, and it doesn’t set cookies or use browser storage. It sends the address of the page (without any ?query or #fragment, which can contain private things like search terms or login links) along with the referrer, if the browser provides one.

Combining example.com and www.example.com

If your site works at both example.com and www.example.com, you can combine them so you see all of your stats in one place. Here’s how:

  1. Add and verify both domains. (We check each one separately, since they don’t always belong to the same person.)
  2. Open the stats page of the one you’d like to keep as your main site, and look for Combine with www.example.com in the Preferences section.

Once they’re combined, your stats, updoots, and hit counters include both domains, and the two count as one site. We still keep each domain’s views separately behind the scenes, so you can split them apart again any time, and nothing gets mixed up.

Your stats

Each site has its own stats page, which you can reach from the menu. Here’s what you’ll find there:

You pick a time range for most stats, so you can see the last 24h, 7d, 30d, 6m, or 1y. We’ll remember the range you pick for each one. The shorter ranges are up to the minute, and the longer ones (6 months and 1 year) are updated once a day.

Want to see more than the top 10? Use the “View all” links under Top pages and Top referrers.

Exporting your data

Your stats are yours, so you can download all of them whenever you like. Use Export your data in a site’s preferences (at the bottom of its stats page) to get a ZIP file with:

CSV files open in any spreadsheet app. There are no IP addresses in the export, because we never store them. Most exports are ready right away; for a really big site, we’ll put it together in the background and email you a link. Download links work for 48 hours, and only while you’re signed in. (Prefer JSON, or want to automate it? The API has you covered.)

Numberless mode

Sometimes it’s nicer not to know exactly how many people are looking. Turn on numberless mode in a site’s preferences (at the bottom of its stats page), and you’ll see rankings and trends instead of view counts:

Updoots and hit counters keep their numbers, since the number is the whole point of them. The API isn’t changed, except that its charts and summary follow the setting too.

Filtering referrers

Sometimes your referrer list fills up with things you don’t care about, like links from your own site or referrer spam. You can hide them!

Add one pattern per line (up to 100). Here’s how patterns work:

Pattern What it hides
example.com Links from example.com and all of its subdomains, like www.example.com.
*spam* The * matches anything, so this hides links from any domain with “spam” in it.
example.com/forum Add a path to be more specific. This hides links from that part of example.com only.

Capitalization and a leading https:// don’t matter. Filters only hide referrers from your lists—your view counts stay the same, and nothing is deleted, so you can change your filters any time.

Traffic alerts

Gone viral? We’ll let you know! Traffic alerts are on for every site by default, so we’ll email you when one of your pages takes off. If you’d rather not get them, uncheck Email me when one of my pages suddenly gets a lot more attention than usual in the Preferences section of your site’s stats page (or use the link in any alert).

Here’s what counts as “taking off”: in the last hour, a page got at least 50 views, at least five times its usual traffic, and a noticeable share of your whole site’s traffic. (That last part keeps busy sites from getting an alert for every little blip.) The email tells you which page it is and where the visitors are coming from, so you can take a look and maybe join the conversation.

You’ll get at most one alert per page per day, and at most three per site per day. Alerts go to the email address on your Neatnik ID, and every alert has a link to turn them off. They only work for sites you’ve verified.

Updoots

Updoots turn any emoji into a button on your pages. Each click makes the number go up. Use Updoots for likes, votes, or your own creative ideas. Here’s one you can test right now:

To add an Updoot to a page on your site, paste this into the source:

<script src="https://neatstats.net/updoot.js" defer></script>
<span class="updoot" data-emoji="⭐️"></span>

You only need the script once per page, and you can add as many updoots as you like. Here are the options:

Option What it does
data-emoji="⭐️" The emoji to show. Use any emoji you like! (If you leave it out, you’ll get a star.)
data-key="…" A name for the updoot. Each page counts its updoots separately, so you only need this if you want two updoots with the same emoji on one page.
data-page="/blog/my-post" Counts the updoot for a different page on your site. It’s handy for a list of posts: give each post’s updoot the address of the post, and it’ll share its count with the updoot on the post itself.
data-slowmode="true" Allows one updoot per IP address per day (it resets at midnight UTC), and turns off press-and-hold. See how slow mode works below.

A few more things to know:

How slow mode works (without storing IP addresses)

To know whether someone has already updooted today, slow mode needs some way to recognize a repeat visit, but we don’t want to store IP addresses. So instead of the IP address, we keep a hash of it.

Specifically, it’s an HMAC (SHA-256) of the IP address, using a secret key that includes today’s date (in UTC), and we only keep the first part of the result. Here’s what that means:

Because it’s based on the IP address, people sharing a connection (like a home or office network) share one daily updoot in slow mode, and someone whose IP address changes might get another one. Slow mode is meant to keep things friendly and fair, not to be bulletproof.

You can see all of your updoots in the Updoots section of your site’s stats page, sorted by the most updoots, the most recent activity, or by page.

Hit counters

Hit counters, baby! Show off how many views a page (or your whole site) has had, in whichever style you like. Here are all of them, counting the views for neatstats.net:

Style What it looks like
plain
rainbow
odometer
flip
lcd
badge
90s
roman

To add one, paste this into any page on a site you’ve added to NeatStats:

<script src="https://neatstats.net/counter.js" defer></script>
<span class="neatstats-counter" data-style="odometer"></span>

You only need the script once per page, and you can add as many counters as you like. Counters show the views that NeatStats has counted, so be sure the view counter is on your pages, too. Here are the options:

Option What it does
data-style="plain" The style to use: plain (the default), odometer, flip, lcd, badge, 90s, roman, or rainbow. (In roman, numbers past 3,999 use a bar over the thousands, the way the Romans did it. Hover over one to see the number.)
data-scope="page" Use page (the default) to count the views of the page the counter is on, or site to count every view your site has ever had.
data-digits="…" For odometer, flip, lcd, and 90s: how many places to show. By default, you’ll get at least 6, plus a spare one once your count reaches 6 digits (to show there’s room to grow). Use a number to pick your own minimum, or 0 for no extra places.
data-label="…" Text to show before the number. For badge, this is the left side of the badge (it says “views” if you leave it out).
data-label-after="…" Text to show after the number.
data-ordinal="true" Shows the number as a place, like “1,235th.” (It adds one, so the person reading it is the next visitor.)
data-animate="count" Counts up from zero when the page loads. This works with plain, lcd, badge, 90s, roman, and rainbow. (The odometer and flip styles always animate.)
data-color="green" For badge: the color of the number’s side. Use green (the default), blue, red, orange, purple, pink, gray, black, or a hex color like #ff6600.

Want an old-school greeting? Try this:

<span class="neatstats-counter" data-scope="site" data-ordinal="true"
  data-label="You’re the " data-label-after=" visitor!"></span>

That shows:

A few more things to know:

API

You can use the NeatStats API to get your stats as JSON, as often as you’d like. It’s great for dashboards, reports, or anything else you dream up. You can also use it to send views and updoots to NeatStats, so you can count all kinds of things.

To get started, generate an API key on your account page. We only show the key once, when it’s created, so be sure to copy it somewhere safe. (If you lose it, you can generate a new one. That will turn off the old key right away.)

Then send your key with each request, like this:

curl https://neatstats.net/api/v1/sites/example.com/views?range=7d \
  -H "Authorization: Bearer YOUR_API_KEY"

Each request is for one of your sites, and your key only works for sites on your account. Here’s what you can get:

Endpoint What you get
/infoBasic info about your site and a summary of its views.
/viewsYour views over time, plus a chart.
/browsersViews by web browser.
/platformsViews by operating system.
/pagesYour top pages.
/referrersYour top referrers (with your referrer filters applied).
/mapLocations for a map, by GeoName.
/countriesViews by country.
/updootsYour pages with updoots, and their counts.

Most endpoints accept a range (24h, 7d, 30d, 6m, or 1y), and many accept a limit and a sort. Check out the full API reference for all of the details and sample responses.

Counting other things

NeatStats isn’t just for web pages! With your API key, you can send us views and updoots from anywhere you can make a web request: your server, an app, a script, or a little gadget on your desk. Here are a few ideas:

Here’s how to record a view:

curl https://neatstats.net/api/v1/sites/example.com/views \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d "path=/downloads/app.zip"

Views you send show up in your stats just like any others, within a few seconds. You can include a referrer, a user agent (for the browser and platform breakdowns), and an IP address (for the map and countries). As always, we only use an IP address to find an approximate location, and we never store it.

Endpoint What it does
POST /viewsRecords a view (or up to 100 at once).
POST /updootsAdds to an updoot’s count. (If the updoot doesn’t exist yet, we’ll create it.)
PUT /updootsSets an updoot’s count to an exact number.
DELETE /updootsDeletes an updoot.

Sending data needs your API key, even if you’re signed in. The full API reference has all of the details.

Need help?

If you run into any issues or have any questions, send an email to help@neatnik.net and we’ll give you a hand.

License & Credits

NeatStats uses the handy flag icons maintained by Panayiotis Lipiridis. (License)