Two browser signals tell your site "do not track me." Most analytics tools ignore at least one of them. Here is what each signal is, what a script can actually do with it, and how to check your own setup in five minutes.
Do Not Track (DNT) is an older browser setting that sends a header and exposes navigator.doNotTrack. Global Privacy Control (GPC) is a newer signal that sends the Sec-GPC: 1 header and exposes navigator.globalPrivacyControl. Both are just flags. Nothing happens unless the site, or the scripts on it, choose to read them.
Want to test your own site right now? Jump to the five-step browser test. Or start with the free GhostMetrics plan and run the test against your own install.
Do Not Track appeared in browsers in the early 2010s as a simple preference: a user ticks a box, and the browser adds a header, DNT: 1, to every request. The same setting is readable from JavaScript as navigator.doNotTrack, which returns the string "1" when the user opted out, "0" when they explicitly opted in, and null or "unspecified" when they did nothing. Older Internet Explorer and legacy Edge exposed the same idea under navigator.msDoNotTrack, and some versions put it on window.doNotTrack.
The weakness of DNT was never the mechanism. It was that nobody was obliged to listen. The header carries no legal force of its own and no enforcement path, so the industry never converged on a common behaviour. Some trackers honour it, many ignore it, and a few browsers have dropped or de-emphasised the setting over the years. If you still see the toggle in a browser's privacy menu, you are looking at a preference that only works when the receiving site chooses to respect it.
That still makes it worth reading. A visitor who turned DNT on went out of their way to express a preference, and a site that ignores it is telling that visitor their choice did not matter. For a privacy-first analytics product, honouring it costs almost nothing: you lose a small slice of pageviews and gain a consistent, defensible policy.
Global Privacy Control was designed as a successor with a clearer purpose. Instead of a vague "do not track me," GPC is a signal that the user wants to opt out of the sale or sharing of their personal data. It is sent as the HTTP request header Sec-GPC: 1 and exposed to scripts as navigator.globalPrivacyControl, a boolean that is true when the signal is on. Some browsers send it by default in their privacy modes, and extensions can add it to browsers that do not. Because the header name starts with Sec-, a web page cannot forge or strip it from script; only the browser sets it.
The practical difference from DNT is how it is positioned. GPC is specified so that sites can treat it as a machine-readable opt-out signal, and a number of privacy regimes have discussed or adopted it in that role. Which regimes, and what they require of your site, is a legal question that changes. This page does not try to answer it. If you need to know whether GPC creates an obligation for your organisation, ask counsel who knows your jurisdictions and your data flows.
From an engineering view the two signals are siblings. Both are booleans a script can read in one line. Both should lead to the same outcome in a tool that takes privacy seriously: the script does nothing. The main difference is that GPC is far more likely to be present today in a privacy-focused browser, while DNT has a longer tail of users with the setting switched on and forgotten.
There are three places a signal can be read, and they matter because each one covers a different gap.
Sec-GPC: 1 or DNT: 1 can drop the event on arrival. The visitor's browser has already sent the request, so the data crossed the network, but it is discarded before storage. This also covers clients that call your collection endpoint directly without running your script.Client-side checking is simple and effective for the common case, a real visitor loading your page in a real browser. Its limit is that it only protects what the script controls. If someone posts events straight to the collection endpoint, the endpoint is the only place that could notice. For site analytics that is rarely a privacy concern, since the person sending those events is not a visitor being tracked, but it is worth knowing where each check lives so you can describe your setup accurately.
One more design point: when the flag is on, skip everything, not just pageviews. A tracker that suppresses the pageview but still sends a custom-event ping when someone clicks a button has not honoured the signal. The same goes for performance beacons. A correct implementation stops at the top of the script so that no code path can send.
GhostMetrics honours Global Privacy Control and Do Not Track by exiting before it sends anything. The check runs once, at the top of gm.js, right after the script confirms it has a site ID. It tests four things: navigator.globalPrivacyControl === true, navigator.doNotTrack === "1", window.doNotTrack === "1" and navigator.msDoNotTrack === "1". If any is true, the script replaces window.ghostmetrics with an object whose track() method does nothing, and returns.
The ordering is what makes this thorough. Every request the tracker can send, the pageview, the leave beacon with time on page and scroll depth, the Core Web Vitals report, the declarative data-gm-event click listener and the SPA route-change pageviews, is set up after that early return. When a flag is set, none of that code is ever reached, so no listeners are attached and no beacons are queued. Your own calls to window.ghostmetrics.track(...) keep working in the sense that they do not throw, because the stub accepts them and discards them. Code that calls the tracker never needs a guard.
Two honest caveats follow from the design. First, the check is client-side. The GhostMetrics collection endpoint does not read the Sec-GPC or DNT request headers, so the protection depends on the script running in the visitor's browser, which is the normal path for a site install but not for a hand-built request. Second, because the visitor sends nothing, you will not see them at all: not as a bounce, not as a direct visit. Your visitor counts are a floor for real traffic, and the gap is the share of your audience running a privacy signal. For a developer or privacy-tool audience that share can be large.
It also helps to place this next to the rest of the privacy model. GhostMetrics sets no cookies, uses no localStorage, stores no raw IP address and keeps no cross-session identifier; the only browser storage it touches is per-tab sessionStorage for a pageview counter and first-touch UTM values. Honouring the signals is an additional layer on top of a design that already collects very little. For the mechanics of how it counts without cookies, read cookieless tracking explained.
Behaviour here varies by product and by configuration, and it changes between releases, so the table sticks to what is well established and points you to the vendor docs for the rest. The reliable method is your own test, covered in the next section; documentation tells you intent, a network panel tells you what happens.
| Tool | Cookies by default | Reads GPC / DNT | Where to confirm |
|---|---|---|---|
| GhostMetrics | No | Yes: client-side, exits before any request (GPC, DNT, msDoNotTrack) | Run the browser test below |
| GA4 | Yes (_ga) | Check current Google documentation | Google's tag and consent docs, then your own network panel |
| Plausible | No | Check current Plausible docs | Plausible's script docs, then the network panel |
| Fathom | No | Check current Fathom docs | Fathom's script docs, then the network panel |
| Umami | No | Configurable; check the tracker options in the Umami docs | The tracker's data attributes, then the network panel |
| Cloudflare Web Analytics | No | Check current Cloudflare docs | Cloudflare docs, then the network panel |
Two things are worth noticing. A tool being cookieless and a tool honouring the signals are independent properties: a cookieless script can ignore GPC, and a cookie-based one can respect it. And "reads the signal" can mean different outcomes, such as suppressing all events, suppressing only some, or only changing which identifiers are used. When a vendor says it respects a signal, ask which of those it means. Broader tool comparisons live in cookieless analytics compared and GA4 alternatives.
You do not need the vendor's word for any of this. Five steps in a desktop browser will tell you what a script does on your own site. The example uses GhostMetrics, but the method is identical for any tracker.
navigator.globalPrivacyControl and navigator.doNotTrack. You should see true and "1". If you see null or an empty result, the signal is off and the rest of the test proves nothing.ghostmetrics). Reload the page.gm.js file is fetched like any script) but should make no collection request: no POST to the events endpoint. A script that sends a pageview with the flag on is not honouring it.Extra credit: with the flag on, click an element that carries a custom-event attribute and scroll the page, then switch tabs. Those actions trigger the click, scroll-depth and leave requests in most trackers. A properly gated script sends none of them. Test in a private window too, since extensions that block trackers can mask the result: if a blocker stops the request, you cannot tell whether the script or the blocker held it back. The Network tab shows blocked requests in red, which is how you tell the cases apart.
If you maintain several sites, repeat the check after any change to your tag setup. A tag manager that wraps the analytics script can sit between the browser flag and the tracker, and the wrapper may or may not pass the check through. Testing the live page is the only test that covers the whole chain. If you are standing up a new install, our guide to adding analytics to a static site shows the one-tag setup this test expects.
Honouring GPC and DNT makes your numbers smaller, and the reduction is not random. Visitors who run privacy browsers, privacy extensions or hardened settings are more likely to send the flags, so the missing slice skews toward technical and privacy-aware audiences. If your readers are developers, expect a bigger gap than for a general consumer site. Treat the dashboard as a consistent sample, good for trends and comparisons between pages, and not as a census.
It does not cost you the things cookieless analytics already gave up. There is no returning-visitor identity to lose, because a tool without cookies or persistent identifiers never had one. Referrers, top pages, entry pages, geography at country and city level, browser and device splits, and Core Web Vitals continue to work for every visitor who has not opted out. For the full list of what the dashboard shows and how to read it each week, see the weekly dashboard routine.
The signals also do not replace the rest of your privacy posture. A GPC check in your analytics script says nothing about the other scripts on your page: ad pixels, chat widgets, embedded video and social buttons each make their own decisions. If the goal is a page that respects the browser's wishes end to end, audit every third-party request in the Network tab with the signal on, not just the analytics one. And whether you need a consent banner at all is a different question again, which we cover in do I need a cookie banner. Treat that as a starting point for a conversation with counsel, since it depends on where your visitors are and what you collect.
GhostMetrics checks Global Privacy Control and Do Not Track on load and sends nothing if either is set. It sets no cookies, uses no localStorage, and stores no raw IP addresses. Install is one script tag, and you can verify the behaviour yourself with the test above. The free plan is free forever: one website, unlimited pageviews, real-time dashboard, every dashboard view, full history.
Pro is $9.99/mo flat with unlimited pageviews, unlimited websites (fair-use ceiling of 250), a public shareable dashboard and a 30-day free trial (card required to start, nothing charged for 30 days, cancel anytime). Raw CSV or JSON export is on every plan, including free. See the pricing page for the current details.
Start free — no card See the live demoDisclosure: GhostMetrics is built by Null Agency and we use it on this site, so we are not a neutral party about our own product. We kept the claims to what its script does in code and pointed to vendor documentation for competing tools. Nothing here is legal advice; consult counsel about obligations that apply to your site. Pricing and behaviour of third-party products can change, so confirm with the vendor.