A plain account of what this thing does
Analytics and uptime monitoring that don't know who you are.
Mignard Analytics counts visits to a small number of websites and keeps an eye on whether those sites are up. It does this without cookies, without keeping anyone's IP address, and without any way to recognise a visitor from one day to the next. This page explains, in full, what is collected, how, and what never is.
The short version
What the script on a site does one small file, no dependencies
A site that uses Mignard Analytics includes one script tag. When a page loads, the script sends a single small message to this server. Here is everything in that message:
| Site key | A short public code that says which site the hit belongs to. It is not a secret and it identifies the site, not the visitor. |
|---|---|
| Page address | The URL of the page being viewed. The server keeps only the path (for example /pricing) and any utm_ campaign labels. The rest of the query string and anything after a # is thrown away. |
| Referrer | The page that linked here, if the browser chose to send one. Only the domain is kept (news.ycombinator.com, not the full link), and only when it's a different site. Navigation within the site is not treated as a referral. |
| Window width | A single number, used only to sort the hit into one of four buckets: mobile, tablet, laptop or desktop. The number itself is not stored. |
| Pageview id | A random id made up by the script for this one pageview. It exists so the "time on page" figure can be attached to the right hit when the visitor leaves. It is never written to the browser and means nothing on its own. |
| Seconds on page | Sent when the visitor leaves or switches tabs. Capped at six hours. |
| Event name | Only if the site owner has chosen to count something specific, such as "signed up". Just the label. |
Like every web request, that message arrives with the visitor's IP address and the browser's user-agent string attached. The next section covers exactly what happens to those.
The script also stays quiet on purpose in a few situations. It does nothing on localhost or when a page is opened from a file, and it does nothing when the browser reports that it's being driven by automation. The server separately ignores anything whose user-agent looks like a crawler, a link-preview fetcher, a monitoring service or an AI bot. Those hits are dropped before anything is written.
How visitors are counted without identifying them
Most analytics tools count unique visitors by putting an id in a cookie. Mignard Analytics has no cookie, so it needs another way to notice that two pageviews five minutes apart came from the same person. It does this with a hash:
visitor = SHA-256( today's salt | site | IP address | user-agent )
The salt is 32 random bytes made fresh every day at midnight UTC. When a new day's salt is created, every earlier salt is deleted. The consequences of that are the whole point:
- The hash can't be reversed. It is a one-way function of the inputs; there is no way back from the stored value to an address.
- The hash can't be recomputed after today. Even someone with the database, a visitor's IP address and their browser details could not reproduce yesterday's hash, because yesterday's salt no longer exists.
- Tomorrow you are a new person. The same visitor produces a different hash each day, so there is no way to say "this person came back on Thursday". The dashboard shows daily uniques and nothing longer.
- Each site gets its own hash. The site is part of the input, so the same person on two different sites produces two unrelated values. There is no cross-site tracking.
The IP address and user-agent string exist in the server's memory for the duration of that one request and are then gone. The address is also used, in memory only, to cap how many messages a single client can send per minute, and to look up a country (see below). Neither use writes it anywhere.
Visits are grouped into sessions with a random id that lives in server memory and is forgotten after thirty minutes of inactivity. If the server restarts, sessions simply start again.
What one pageview looks like in the database
This is the complete record kept for a pageview. There are no other columns.
| When | Date and time, in UTC. |
|---|---|
| Visitor hash | The daily one-way value described above. |
| Session id | A random id shared by the pageviews of one visit. |
| Path | The page path, after the privacy rules below have been applied. |
| Referrer domain | Just the domain, only for external referrers. |
| Campaign labels | The utm_source, utm_medium and utm_campaign values if the link had them. |
| Country | A two-letter country code, or nothing. |
| Device class | Mobile, tablet, laptop or desktop. |
| Browser family | "Firefox", "Safari", "Chrome" and so on. Never a version number. |
| Operating system family | "macOS", "Windows", "Android" and so on. Never a version number. |
| Seconds on page | Filled in when the visitor leaves. |
| Event name | Only for custom events. |
Paths can carry identifiers, so they are scrubbed
A page address like /orders/48213 or /users/ab12cd… says something about the person viewing it. A site owner can switch on id collapsing, which rewrites any path segment that is a number, a UUID or a long hex token to :id before it is stored, so all of those pages are filed under one row: /orders/:id. They can also add their own rewrite rules for whatever else their URLs contain. Either way the hit still counts; only the label changes.
Country without the address
The country code comes from one of two places. If the site sits behind a CDN that supplies a country header, that is used. Otherwise the address is looked up in an IP-to-country database that runs on this server, so the lookup never leaves the machine. Only the two-letter code is kept. There is no city, region or coordinate data anywhere in the system.
What is never collected
- IP addresses
- The full user-agent string, or browser and OS versions
- Screen resolution, colour depth, installed fonts, canvas or audio fingerprints
- Browser language or time zone
- Cookies, local storage or any browser-side identifier
- Query strings other than the three campaign labels
- URL fragments (anything after
#) - Names, email addresses, user ids or account details
- Anything typed into a page, clicked, scrolled or hovered
- Mouse movements, keystrokes or session recordings
- Anything about a visitor across more than one day or more than one site
If it isn't in the table above, it isn't in the database.
Uptime monitoring looks at the site, not its visitors
Monitoring works in the opposite direction from analytics. Nothing runs in anyone's browser. This server requests the site's address every few minutes and records whether it answered.
Each check stores the time, whether it passed, the HTTP status code, how many milliseconds the response took, and a short error message if something went wrong. A monitor can be asked to look for a word in the page; the page body is read for that comparison and then discarded. Check history is kept for ninety days by default, and the incident log (when the site went down and came back) is kept permanently.
Alongside that, the certificate is read to record its expiry date and issuer, and the domain's expiry date is read from the public registry (RDAP). Both are public facts about the site.
Every request from the monitor identifies itself with a user-agent that names this service, so it is visible as a monitor in the site's own logs and is easy to filter.
A heartbeat monitor is the one case where the site contacts us: a scheduled job pings a URL containing a random token, and the time of the last ping is stored. Nothing else about the job is recorded.
A site owner can choose to publish a status page. It shows only the monitors they have marked public, by name, with uptime bars and recent incidents. It is off unless switched on.
Site checkups
A checkup crawls the site's public pages the way a search engine would, starting from the home page and following internal links, up to a couple of hundred pages. It looks for broken links, missing titles, redirect chains, a missing robots.txt and similar housekeeping problems. For each page it keeps the address, the status code and a hash of the content, so the next crawl can tell what changed. The page content itself is not stored.
One part of a checkup leaves this server. If a PageSpeed key has been configured, the addresses of a handful of pages (the home page, the most-visited pages and any that just changed) are sent to Google's PageSpeed Insights API to get Lighthouse scores. Google then fetches those public pages itself. Apart from the optional guidance described below, this is the only third party any part of the system talks to about a site's content, and it only ever sees page addresses that are already public.
Checkups know nothing about visitors. They use the analytics only to decide which pages are worth scoring.
Contact forms
A site can point its contact form at this server instead of running its own form backend. A contact form is the one place where personal information arrives on purpose: the visitor types their name and email because they want a reply. What is stored is exactly the fields they filled in, plus the address of the page the form was on. The visitor's IP address is not stored with the message.
Spam is handled without a CAPTCHA and without any third-party service. A hidden field that only robots fill in, a check for submissions that arrive impossibly fast after the page loads, a per-client rate limit held in memory, and a check that the post really came from the site it belongs to. Messages flagged as spam are kept out of the inbox but are not sent anywhere for analysis.
New messages are emailed to the people who look after the site. That email contains the message, so it goes through whichever mail provider the site owner has configured.
Google Search Console optional
A site owner can connect their Google Search Console property so the dashboard also shows which search queries brought people in. The connection is read-only. The Google token that makes it work is encrypted before it is stored and is used for nothing except fetching those query reports. No analytics data flows the other way to Google.
AI guidance optional, and only when asked for
Each site's dashboard has an Ask for guidance button. When someone presses it, the numbers on that page are written up as a short brief and sent to Anthropic's Claude, which replies with a plain-English read: what's going well, what needs attention, what to do this week, and where there isn't enough data to say. Nothing is sent automatically, on a schedule, or without that button being pressed, and a site owner can remove the button from their site altogether.
The brief contains only what the dashboard itself shows: visitor and pageview totals, the paths of popular pages, referring domains, country and device counts, uptime figures, checkup findings, Lighthouse scores, search targets and the figures Google reports for them. It never contains visitor hashes, session ids, IP addresses or anything else from the raw events, because none of those could identify anyone anyway, and it never contains the contents of contact-form messages. The brief that went out is stored alongside the answer, so anyone with access to the site can read exactly what was sent.
Anthropic processes the request under its commercial API terms, which state that data sent through the API isn't used to train its models. It is the second and last outside service any part of the system talks to about a site, after Google's PageSpeed API.
Where the data lives, and who can see it
Everything is in one PostgreSQL database on a single server hosted on Railway. There is no analytics vendor behind the scenes; this is the whole system.
Each person with a login sees only the sites they have been given access to. Paul Mignard runs the service and, as its administrator, can see every site.
Raw data is kept for as long as the service runs, unless the owner asks for it to be trimmed after a set number of days. That sounds like the opposite of privacy, but remember what the raw data is: the table above, with no way to tie any row to a person. Keeping it means the site owner can always look back. The owner can also download everything about their site as CSV at any time, so nothing is held hostage.
Cookies
On the sites being measured: none. The script never sets one, and the server never asks the browser to.
On this dashboard: one, and only after signing in. It is the sign-in cookie that keeps you logged in, it is sent only to this domain, and it expires after two weeks of not being used. Nobody who merely visits a measured site ever touches this domain, so they never see it.
Does a site using this need a cookie banner?
The design is intended to make the answer no. Consent banners exist because conventional analytics store identifiers on a visitor's device and keep personal data such as IP addresses. Mignard Analytics does neither: it stores nothing on the device and keeps no personal data, and the only derived value, the visitor hash, cannot be turned back into a person and stops working at the end of the day.
That is a description of how the software behaves, not legal advice. Whether a particular site needs to say something to its visitors depends on where it is, who its visitors are, and what else the site does. If in doubt, ask someone whose job that is.
Been given a login?
Sign in to your dashboardThe sign-in page is at analytics.mignard.co/account/login · Privacy policy