Product analytics without creeping out your users
You can learn what actually happens in your product without tracking people across the web. Here is the honest middle ground between flying blind and being creepy.

Most product analytics setups land in one of two bad places. Either you have nothing and you are guessing about what users do, or you bolted on six tracking scripts that follow people around the internet, slow your site down, and quietly become a legal liability. There is a sane middle, and it is closer than you think.
What you actually want to know
Before picking a tool, get clear on the questions. Founders often say "we need analytics" when they really mean one of a few specific things:
- Are people getting through onboarding, or dropping off at step three?
- Which features get used, and which ones we built and nobody touches?
- Where does the signup funnel leak?
- Did the change we shipped last Tuesday make activation better or worse?
Notice that none of those require knowing a user's name, their other browsing habits, or their device fingerprint. They require knowing what happens inside your product, in aggregate. That distinction is the whole ballgame. The moment you start collecting data you do not need for a decision you are about to make, you have crossed from product analytics into surveillance, and you have taken on risk for no payoff.
Product analytics versus the creepy stuff
Product analytics is counting events in your own app: "signup_completed," "project_created," "invite_sent." The creepy stuff is third-party tracking pixels, cross-site identifiers, session recordings that capture everything someone types, and ad-network scripts that exist to build a profile of a person across the whole web. You can have the first without any of the second.
The privacy-friendly toolbox
Here is roughly what your options look like, from lightest to heaviest.
Cookieless page analytics. Tools like Plausible, Fathom, or a self-hosted Umami give you traffic, referrers, and top pages without cookies and without personal data. They are tiny (the script is often under 2 KB versus 45 KB or more for the heavy hitters), they do not need a cookie banner, and setup is genuinely an afternoon. Rough cost: free if self-hosted on a small box, or somewhere around 10 to 30 dollars a month hosted for an early-stage app. This answers "how much traffic and from where," not "what do users do inside the app."
Event-based product analytics. This is the real work. PostHog (self-hostable, generous free tier) and Amplitude are the common picks. You instrument named events in your code, then build funnels and retention charts on top. Self-hosting PostHog gives you control and keeps data on your own infrastructure, which makes the privacy story easy to explain. Budget a few hundred dollars a month at modest scale on the hosted plans, less if self-hosted, though self-hosting means you now own the database and its upkeep.
Session replay. Useful, and the most likely thing to bite you. If you record sessions, mask every input by default and only unmask what you deliberately decide is safe. Otherwise you will capture passwords, card numbers, and private messages, and that recording is now the most sensitive data in your company.
Instrumentation: the part teams get wrong
The tool is the easy decision. The thing that determines whether your analytics are useful in a year is your event naming, and almost everyone does it ad hoc until it becomes a swamp.
Decide on a convention before you write the first event. Pick object_action in past tense and stick to it: project_created, invite_accepted, subscription_canceled. Keep properties consistent (plan, source, team_size). Write the list of approved events down somewhere a human reads, and treat adding a new one as a small decision, not a free-for-all. Six months in, the difference between a team that did this and a team that did not is the difference between "let me pull that funnel in two minutes" and "well, we have clicked_button, btn_click, and ClickedButton, so nobody trusts the numbers."
A thin wrapper keeps call sites clean and gives you one place to enforce the rules:
// analytics.ts
type EventName = 'signup_completed' | 'project_created' | 'invite_sent';
export function track(event: EventName, props?: Record<string, string | number>) {
// No PII in props. Names, emails, raw input values do not belong here.
posthog.capture(event, props);
}The TypeScript union is doing quiet work: a typo or an invented event name fails the build instead of silently polluting your data, a practical payoff of strict typing. That one line saves you from the naming swamp.
Staying on the right side of the line
You do not need a lawyer to get the basics right, though you should talk to one before launch in a regulated space.
- Collect for a decision, not "just in case." If you cannot name the chart an event feeds, you probably do not need the event.
- Avoid personal data in event properties. Use a stable internal user ID, not an email, as the identifier. You can join to the real user in your own database when you genuinely need to, and keep that join out of the analytics tool.
- Honor Do Not Track and offer an opt-out for anything beyond plain aggregate counts. It is a few lines of code and it is the decent thing to do.
- Know your obligations. GDPR and similar rules care a lot about whether data is personal and whether it leaves for a third party. Cookieless, aggregate, first-party analytics is the easy mode here. The more you drift toward third-party trackers and identifiable data, the more consent banners and paperwork you inherit.
The reward for staying disciplined is not only legal comfort. A lean setup loads faster, which helps the same conversion numbers you are trying to measure. Every tracking script you add is weight on the page and a third party you now trust with your users.
A realistic rollout
For a typical early-stage app, here is a timeline that holds up. Day one: drop in cookieless page analytics, no banner needed. Week one: stand up PostHog (hosted to start, so you are not babysitting a database during launch) and instrument the five events that map to your activation funnel. That is usually signup, a first meaningful action, and the aha moment, not forty events. Over the following weeks: build the funnel and retention charts, watch them against real releases, and add events only when a specific question demands one.
The instrumentation is maybe one to two days of focused engineering for those first events, plus the ongoing discipline of adding new ones carefully. It is not a huge project. The trap is treating it as a one-time install rather than a small habit.
The takeaway
You can understand your product without creeping out the people using it. Start with cookieless page analytics for traffic, add first-party event analytics for the handful of actions that define activation, name your events like you will still be reading them next year, and keep personal data out of the analytics layer entirely. That setup is faster, cheaper, easier to defend, and (the part people miss) actually clearer to reason about than the kitchen-sink alternative.
If you want a hand wiring this up without it turning into a tracking-script free-for-all, that is squarely the kind of work we like.