One Month After Launch, You Still Can't Answer Three Questions: A Hands-On Analytics Guide for Vibe-Coded Projects
AI helped you ship a tool in four days, but a month later you can't answer: how many people visited, where they came from, where they dropped off. This hands-on guide ships a complete analytics setup in three days — tool selection, 5 core events, Next.js tracking code, privacy compliance, and three weekly reports that turn data into decisions.

AI Wrote Your Features, But Never Gave You Eyes
Last month I was chatting with a friend. He built a PDF-to-Markdown tool with Claude — four days from the first prompt to launch and collecting payments. A month after launch I asked him: how many people visit each day? Where do they come from? How many sign up and then leave without ever touching a core feature?
He went quiet for a long time, then said all he had was a Vercel traffic curve and three Stripe orders. How many people came, where they came from, where they dropped off — he couldn't answer a single one. AI wrote the features, but nobody installed the eyes.
This is the reality for most vibe-coded projects: prompts written at lightning speed, the launch button pressed with confidence, and then a month spent in a Schrödinger state of "someone seems to be using it, or maybe no one is." Analytics sounds like a big-company luxury, but for a solo project it's actually the cheapest investment you can make — because you have no product manager reading the data for you; you are the product manager. You have no growth team running experiments; you are the growth team. Without data, even "what should I fix" is a guess.
This guide isn't about advanced data science. It's a complete playbook a solo developer can ship in three days and then maintain in one hour a week: which tool to pick, how to design events, what the code looks like, how to stay compliant, and how to turn numbers into action.
Picking a Tool: PostHog vs. Umami vs. Plausible
There are plenty of analytics tools out there, but a one-person team's selection logic is completely different from a big company's. Big companies care about permission systems and BI integrations. You care about three things: whether the free tier is enough, how painful deployment and maintenance are, and whether you can do the analysis that actually matters — funnels and retention — instead of just staring at a pageview curve.
Conclusion first: most vibe projects should just pick PostHog Cloud. It has a generous free tier, and events, funnels, retention, and A/B testing all come in one box, with a one-line SDK initialization. The table below is for people who insist on controlling everything themselves or have extreme privacy requirements.
| Dimension | PostHog | Umami | Plausible |
|---|---|---|---|
| Positioning | Full product analytics (events + funnels + retention + experiments) | Lightweight traffic stats, a minimal Google Analytics alternative | Lightweight, privacy-friendly stats, no cookies |
| Deployment | Cloud works out of the box; Docker self-hosting also supported | Self-hosted only (Node + database) | Cloud works out of the box; self-hosting also supported |
| Free / cost | Cloud has a free tier that's usually plenty for a solo project; check official pricing | The software itself is free; the cost is your server and maintenance time | Cloud is a monthly subscription; self-hosting is free but you do the ops |
| Privacy | Optional EU data hosting, supports cookieless mode and an opt-out API | Data lives entirely on your own server, no third parties | Cookie-free by default; GDPR-friendliness is its selling point |
| Funnels / retention | Natively supported — its biggest advantage | Not supported; page visits only | Basic funnels only |
| Maintenance | Zero maintenance on Cloud; self-hosted means you manage the database and upgrades | You handle backups, upgrades, and uptime yourself | Zero maintenance on Cloud |
How to choose, in one sentence: if your project has signups, core features, and payments — i.e., you need to answer "where in the flow do users drop off" — pick PostHog. If it's just a static showcase page and all you want is daily visitors and referrers, self-hosted Umami or Plausible Cloud is lighter and faster. My advice: don't spend two hours a week babysitting an analytics service to save a small subscription fee. For a one-person team, your time is the most expensive line item.
One more word on self-hosting. Many indie developers have a fixation: data must live on their own machines. The instinct isn't wrong, but do the math honestly: self-hosting PostHog means running a full stack of Postgres, ClickHouse, and Redis (check the official docs for details), and upgrades and backups are all on you. Unless your users explicitly require data residency, or you're in a compliance-sensitive industry, the Cloud plan with EU data hosting is more than enough. Spend the saved time improving conversion rates — the return is far higher.
Event Design: Naming Convention First, Tracking Second
With the tool installed, the second trap is event naming. I've seen event lists that look like this: click1, test_event, button_click_final_v2. Three months later not even the author can read them, and the data is dead. Event design has exactly one iron rule: set the naming convention first, and never change it afterward — renaming breaks historical data.
I recommend verb_object in snake_case, all lowercase English:
signup_completed— signup finished (notsignup; only the completed state means anything)project_created— the user created their first project / document / taskcore_action_completed— the user completed the product's core action (generate, export, publish… defined per your product)paywall_viewed— saw the paywallcheckout_started— entered the payment flowpayment_succeeded— payment went through
Beyond naming, each event should carry key properties. payment_succeeded should include plan and amount; core_action_completed should include action_type. Properties are ammunition for future analysis — over-instrumenting costs nothing, but you can never backfill what you didn't capture.
The 5 Core Events Every Solo Project Needs
Don't start by instrumenting 50 events. Make sure these 5 are accurate first — they map to the 5 critical nodes of the user lifecycle:
signup_completed: who the user is. Before signup you only have an anonymous ID; signup is the identity watershed.onboarding_finished: the user completed onboarding. This is where "activation" begins, and where a huge share of churn happens.core_action_completed: the user's first completion of the product's core value action — your "aha moment." Generating a first resume, exporting a first video, publishing a first article.paywall_viewed: the user showed purchase intent. Even without paying yet, this event tells you real demand exists.payment_succeeded: the user paid. The one north star that needs no explanation.
Strung together, these 5 events form a complete funnel: visitors → signups → activated users → would-be payers → paying customers. Each step's conversion rate is next week's optimization target. Everything else (shares, invites, settings changes) can wait until these 5 are running smoothly.
Identity: From Anonymous Visitor to Known User
When a user first visits, the analytics tool assigns an anonymous ID (distinct_id). After they sign up, you call identify to bind the anonymous ID to the real user ID, so pre-signup behavior (which landing page they saw, which button they clicked) connects into one continuous journey with post-signup behavior.
In PostHog this is simple: call posthog.identify(userId) once after login or signup succeeds, and historical anonymous events are automatically attributed to that user. Call posthog.reset() on logout so the next person on the same device doesn't get mixed in. One handy trick: set person_profiles to identified_only at init, so anonymous visitors don't each generate a person profile — it saves event quota and keeps analysis cleaner, since registered users are the ones you actually care about anyway.
PostHog in Practice: From npm install to Your First Funnel
The example below uses a Next.js App Router project — the most common stack for vibe-coded projects. The idea is identical for any framework: initialize the SDK once, wrap a track function, call it everywhere.
Step 1: Initialize
npm install posthog-js
// app/providers.tsx
'use client'
import posthog from 'posthog-js'
import { PostHogProvider } from 'posthog-js/react'
if (typeof window !== 'undefined') {
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
// Only create profiles for identified users; anonymous visitors don't consume quota
person_profiles: 'identified_only',
// Auto-capture pageviews (including client-side route changes)
capture_pageview: 'history_change',
})
}
export function PHProvider({ children }: { children: React.ReactNode }) {
return <PostHogProvider client={posthog}>{children}</PostHogProvider>
}
Then wrap your root layout:
// app/layout.tsx
import { PHProvider } from './providers'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<PHProvider>{children}</PHProvider>
</body>
</html>
)
}
Two values go in your environment variables: NEXT_PUBLIC_POSTHOG_KEY is the project API key, and NEXT_PUBLIC_POSTHOG_HOST is the ingestion endpoint (Cloud US, Cloud EU, or your self-hosted domain — check the official docs). Note the key must have the NEXT_PUBLIC_ prefix, or the client can't read it.
Step 2: Wrap Event Tracking
Don't scatter posthog.capture through your business code. A wrapper gives you three wins: swapping SDKs never means a site-wide rewrite, you can attach common properties in one place, and unit tests are easy to mock.
// lib/analytics.ts
import posthog from 'posthog-js'
type EventProps = Record<string, string | number | boolean | undefined>
/** Fire a business event; automatically skipped during server-side rendering */
export function track(event: string, props?: EventProps) {
if (typeof window === 'undefined') return
posthog.capture(event, props)
}
/** Call after signup/login succeeds to attribute anonymous behavior to the real user */
export function identifyUser(userId: string, traits?: EventProps) {
if (typeof window === 'undefined') return
posthog.identify(userId, traits)
}
/** Call on logout so a shared device doesn't mix users together */
export function resetUser() {
if (typeof window === 'undefined') return
posthog.reset()
}
Calls in business code then look like this — clean enough to seem uninstrumented:
// Where the user completes the core action
import { track } from '@/lib/analytics'
async function handleExport() {
const result = await exportPdf(fileId)
track('core_action_completed', { action_type: 'pdf_export', pages: result.pages })
}
// In the signup success callback
import { identifyUser } from '@/lib/analytics'
identifyUser(user.id, { plan: 'free', signup_source: 'landing_v2' })
Step 3: Dodge Ad Blockers (Optional but Recommended)
A harsh reality: a meaningful share of technical users run ad blockers, which nuke analytics scripts outright — your data will systematically undercount. A cheap fix is a reverse proxy: route ingestion through your own domain and blockers can't recognize it. In Next.js it's a few lines of rewrites:
// next.config.ts
const nextConfig = {
async rewrites() {
return [
{
source: '/ingest/static/:path*',
// Replace with your actual PostHog region; check the official docs
destination: 'https://us.i.posthog.com/static/:path*',
},
{
source: '/ingest/:path*',
destination: 'https://us.i.posthog.com/:path*',
},
]
},
}
Then change api_host in init to /ingest. Same-domain ingestion cuts the block rate dramatically. The same trick works for Umami and Plausible — the principle is identical.
Step 4: Build Your First Funnel and Retention View
With code instrumented, build two views in the PostHog dashboard. These are the only two you'll check each week:
Funnels: put signup_completed → onboarding_finished → core_action_completed → paywall_viewed → payment_succeeded in order, with a 7-day window. It shows each step's conversion rate and drop-off count. Nine out of ten people seeing their first funnel gasp — it turns out 80% of signups never even finish onboarding.
Retention: use core_action_completed as the return event and see how many registered users come back on day 1, 7, and 30. The retention curve is a health checkup for your product: day-1 retention under 20% means the product isn't hitting a need; a cliff at day 7 means friction in the core flow.
Don't get greedy — pin these two views to the top of your PostHog dashboard. The system is truly running when you can say, looking at the funnel, "last week's onboarding step-3 change lifted activation 6 points."
Cost Control: Don't Blow the Free Tier by Month-End
PostHog-style tools bill by event volume. The free tier is usually plenty for a solo project, but there are two invisible killers: autocapture and high-frequency events. Autocapture records every click and keystroke — one power user can generate thousands of events a day. My advice: keep autocapture on during development for inspiration, turn it off before launch, and keep only your 5 designed core events plus essential pageviews.
The other common waste is firing high-frequency events like "heartbeat," "scroll depth," or "mouse move" at full volume. If you genuinely want to know whether users finish a long article, fire once at each of the 25%, 50%, and 100% scroll thresholds — not once per pixel. Instrumentation is like code: restraint is a virtue.
Finally, spend five minutes at the start of each month glancing at the usage dashboard. If event volume is approaching the free-tier ceiling, first check whether autocapture was left on, or whether track got called inside a loop — I've seen a missing dependency array in a useEffect fire tens of thousands of events from a single page. Quota is for analyzing users, not feeding bugs.
Privacy Compliance: Don't Wait for the Complaint
Many indie developers think "with my traffic, who cares about compliance." But GDPR applies the moment you have a single EU user, and app stores and payment platforms keep tightening privacy-policy requirements. Compliance isn't a big-company privilege — it's a checklist item you can knock out in passing.
Three things are non-negotiable:
- Cookie consent banner: show it to EU users on first visit, and don't initialize the analytics SDK until they accept. Implementation is simple: delay
posthog.inituntil consent, or callposthog.opt_out_capturing()first andposthog.opt_in_capturing()after they agree. You don't need to build the banner yourself — open-source components are everywhere. - Say it in your privacy policy: state which analytics tool you use, which events you collect, where the data lives (e.g., PostHog's EU region), and how users can request deletion. AI writes privacy policies fast, but verify every line — don't let it promise something you don't actually do.
- Data retention period: set one (say, 12 months) and let old event data expire automatically. PostHog supports configuring retention policies — check the official docs and your plan. Hoarding years of data you'll never use adds breach risk and zero value.
One more warning: never put passwords, tokens, ID numbers, or anything sensitive in event properties. PostHog captures page URLs and some page content by default — check that autocapture isn't sweeping user input out of form pages. It's the most common and most fatal category of analytics incidents; one is enough to destroy user trust.
Deciding With Data: Three Reports a Week
Data creates no value by itself — decisions do. A common trap is building a dozen dashboards, glancing at them weekly, and changing nothing. For a one-person team I recommend exactly three reports a week, each tied to an action:
| Report | What to look at | What it triggers |
|---|---|---|
| Traffic & sources | Weekly visitors, channel mix, landing-page bounce rate | A channel with big traffic but low signup conversion → the landing page copy or hero section is broken; ship a new version and measure |
| Activation funnel | Step-by-step conversion: signup → onboarding → core action | Low onboarding completion → cut steps or add progress cues; low core-action conversion → move the core feature entrance earlier |
| Retention & payment | 7-day retention curve, paywall-view → payment conversion | Retention cliff → go talk to churned users (5 emails beat 5 dashboards); low payment conversion → check whether the pricing page actually explains the value |
Two real decision stories. First: a tools site found Product Hunt drove 40% of traffic but converted to signup at one-third the rate of organic search. The conclusion wasn't "PH is useless" — PH users came to window-shop, so the landing page hero needed an instant value promise like "generate your first resume in 30 seconds" instead of brand storytelling. Conversion doubled after the change.
Second: an AI writing tool saw only 15% conversion from onboarding_finished to core_action_completed. Finer-grained events revealed users were stuck on "choose a writing template" — too many options. They killed template selection, defaulted to one general template, and conversion rose to 41%. An afternoon's work — but without funnel data, the author would probably still be polishing the template library he was so proud of.
Both stories share one trait: data locates the problem; the solution comes from your understanding of users. Analytics tells you "60% of people drop at this step," but "why" always requires talking to users and walking the flow yourself. Data is the CT scan, not the diagnosis.
Launch Checklist: Tick Every Box Before Shipping
Save this list and run through it every time you launch a new project. Ticking everything takes half a day at most, and it prevents 90% of analytics rework:
- SDK initialized; test events visible in real time in production (walk the flow yourself and confirm all 5 core events fire)
- Event names follow the
verb_objectconvention and are documented somewhere (even a table in the README) - identify called on signup/login success; reset called on logout
- Reverse proxy against ad blockers configured (or blocker rate confirmed acceptable for your audience)
- Funnel view built: signup → onboarding → core action → paywall → payment
- Retention view built, with the return event set to the true core action
- Cookie consent banner live; SDK not initialized before consent
- Privacy policy states the analytics tool, collection scope, data storage location, and deletion process
- No passwords, tokens, or sensitive data in event properties; form pages checked for autocapture leakage
- Data retention period set; no indefinite hoarding
One last honest word: perfectionism is the biggest enemy of analytics. I've seen people spend two weeks designing the "perfect event taxonomy" for a product that had no users three months after launch — a beautiful taxonomy over zero data. The order is always: ship first, get users first, instrument the 5 core events first, then iterate. Analytics is the tool that takes you from 1 to 10, not the prerequisite for 0 to 1. Install the eyes — but don't let installing them stop you from walking.
Related articles

AI-generated project scaffolds ship with no search, and users who can't find anything assume the product is empty. This guide covers a three-layer mental model, a Postgres tsvector vs. Typesense comparison with runnable code, and the details that matter: debouncing, highlighting, empty states, typo tolerance, plus a launch checklist.

Traffic is moving from the search box to the AI answer box. A vibe coder ships a product in a week — and nobody finds it. This guide turns the SEO fundamentals (sitemaps, JSON-LD, Core Web Vitals) and the new AI-discovery toolkit (llms.txt, per-page Markdown versions, FAQ schema, agent-readable pricing and API docs) into a shippable 30-day checklist. The core judgment: how well you document sets your product's ceiling in the agent economy.

The Zephos team planted 16 launch-killer bugs in Notely, an agent-built Next.js + Supabase + Stripe notes app — two payment-related: unsigned webhooks accepted, pro granted from a self-declared client_reference_id. This guide turns those traps into a playbook: webhook signature verification, a server-side single source of truth, the subscription state machine, test clocks, and a launch checklist. Money logic must be hand-written or audited line by line.