50% off SaaS Starter Kit — only for the first 100 buildersGrab it →
← Back to blog
best-practicesMay 18, 2026·9 min read

Analytics for Indie Devs — What to Actually Measure (And What's Just Noise)

Most indie devs either track nothing or drown in dashboards. Here's what we actually look at, what we ignore, and why vanity metrics will gaslight you.

Robert Seghedi

Robert Seghedi

Co-founder, peal.dev

Analytics for Indie Devs — What to Actually Measure (And What's Just Noise)

We spent three months staring at a Mixpanel dashboard with 47 custom events, feeling very professional and very data-driven, while completely missing that 60% of our users were dropping off because a button was broken on mobile Safari. The data was there. We just weren't measuring the right things.

Analytics for indie devs is a weird problem. You're not Google. You don't have a growth team running A/B tests. You're two people trying to figure out if anyone actually uses the thing you built, and if not, why not. The tooling is built for enterprise teams with dedicated analysts, and most of the advice online is written for those teams too. So let's fix that.

The Only Metric That Matters at First

Before you install anything, answer this: do you have retention? Are people coming back? Everything else — pageviews, signups, conversion rate — is secondary to whether the people who tried your thing found enough value to return. If they're not coming back, no amount of funnel optimization will save you. You're filling a leaky bucket.

For a SaaS, retention looks like weekly or monthly active users. For a content site, it's returning visitors. For a marketplace, it's repeat transactions. Define it specifically for your product before you open a single analytics tab. Write it down. Tattoo it on your monitor if you need to.

If you can only track one thing, track whether users come back 7 days after signup. That single number will tell you more about product-market fit than any vanity metric.

What We Actually Track (The Short List)

After a lot of trial and error, we've converged on a pretty minimal setup. Here's the actual list, not the aspirational one:

  • Signups per day/week — are people showing up?
  • Activation rate — of people who signed up, how many completed the core action (uploaded a file, created a project, sent their first message — whatever your 'aha moment' is)
  • Day 7 and Day 30 retention — the two numbers that tell you if you have a real product
  • Churn rate for paid users — monthly, and you should feel it in your chest when it's bad
  • Where traffic is coming from — not to obsess over channels, but to know which ones aren't total noise
  • Error rate and p95 response times — because slow or broken things kill retention before analytics can even measure it

That's it. Six things. You could track all of this with a spreadsheet and some SQL queries if you wanted to. The point is not the tool, it's the discipline of actually looking at the numbers weekly and being honest about what they're telling you.

Vanity Metrics and Why They'll Gaslight You

Pageviews are the big one. Everyone loves pageviews. They go up when you post on Hacker News, they spike when someone big tweets about you, and they make you feel like something is happening. Usually nothing is happening. We once had a week with 10x normal traffic because a Reddit thread linked to us, and we got exactly two signups from it. The pageview graph looked incredible. The business impact was zero.

Social media followers, newsletter open rates, GitHub stars — all of these have the same problem. They measure attention, not value. Attention is nice, but you can't build a business on it unless you convert it to something real. Track them if you want, but never let them be the headline metric in your weekly review.

Time on page is another sneaky bad one. Long time on page sounds great until you realize people are spending 8 minutes on your pricing page because they're confused about what your product actually does. Or they left the tab open and went to make coffee. Engagement metrics need context to mean anything.

Setting Up the Minimum Viable Analytics Stack

For most indie projects, you need three things: something for product analytics (user behavior), something for performance monitoring (is it working), and something for error tracking (when it breaks). Here's the stack we actually use and recommend:

For product analytics, Posthog on the free tier covers almost everything you need. It's open-source, you can self-host if you care about that, and the session recording feature alone has saved us dozens of hours of trying to reproduce bugs. Here's the minimal setup in Next.js:

// lib/posthog.ts
import posthog from 'posthog-js'

export function initPosthog() {
  if (typeof window === 'undefined') return
  if (!process.env.NEXT_PUBLIC_POSTHOG_KEY) return

  posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
    api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST ?? 'https://app.posthog.com',
    // Don't track in development
    loaded: (ph) => {
      if (process.env.NODE_ENV === 'development') ph.opt_out_capturing()
    },
    // Capture pageviews automatically
    capture_pageview: false, // We'll do this manually for SPAs
    persistence: 'localStorage',
  })
}

// The events we actually care about
export function trackSignup(userId: string, plan: string) {
  posthog.identify(userId)
  posthog.capture('user_signed_up', { plan })
}

export function trackActivation(userId: string, activationEvent: string) {
  posthog.capture('user_activated', { activation_event: activationEvent })
}

export function trackUpgrade(userId: string, fromPlan: string, toPlan: string) {
  posthog.capture('user_upgraded', { from_plan: fromPlan, to_plan: toPlan })
}

For performance and error tracking, Sentry on the free tier is the obvious choice. The amount of time it's saved us by giving us actual stack traces instead of vague 'something broke' reports is incalculable. Set it up once, forget about it, and let it yell at you when things go wrong.

// In your Next.js app, sentry.client.config.ts
import * as Sentry from '@sentry/nextjs'

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  
  // Only sample a percentage of transactions in production
  // 1.0 means 100% which is fine for low-traffic indie projects
  tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
  
  // Don't send errors in development
  enabled: process.env.NODE_ENV === 'production',
  
  // Tag errors with the user so you can see who's affected
  beforeSend(event, hint) {
    // You can filter out errors you don't care about here
    // e.g., browser extension errors, network errors, etc.
    const error = hint.originalException as Error
    if (error?.message?.includes('ResizeObserver loop')) {
      return null // This one is always noise
    }
    return event
  },
})

The Retention Query You Should Run Every Week

If you're storing user data in Postgres (and you should be), you can write your own retention queries. This is more reliable than trusting an analytics tool's definition of 'active', because you define what 'active' means for your product.

-- Day 7 retention: users who signed up 7-14 days ago
-- and were active in the last 7 days
-- Replace 'events' and 'users' with your actual table names
-- Replace 'created_at' and 'last_active_at' with your columns

WITH cohort AS (
  SELECT 
    id,
    created_at::date AS signup_date
  FROM users
  WHERE 
    created_at >= NOW() - INTERVAL '14 days'
    AND created_at < NOW() - INTERVAL '7 days'
),
retained AS (
  SELECT DISTINCT user_id
  FROM events  -- or sessions, or whatever 'active' means for you
  WHERE created_at >= NOW() - INTERVAL '7 days'
)
SELECT
  COUNT(c.id) AS cohort_size,
  COUNT(r.user_id) AS retained_users,
  ROUND(
    COUNT(r.user_id)::numeric / NULLIF(COUNT(c.id), 0) * 100,
    1
  ) AS retention_rate_pct
FROM cohort c
LEFT JOIN retained r ON r.user_id = c.id;

Run this every Monday. If the number is going down, that's the only thing you should be working on. Not new features. Not marketing. Figuring out why people aren't coming back.

When to Add More Tracking (And When Not To)

There's a right time to add more detailed event tracking, and it's when you have a specific question you can't answer with what you already have. Not 'it would be interesting to know if people click this button.' A real question: 'We think people are dropping off somewhere in the onboarding flow, but we don't know where.' That's a question that justifies adding funnel events.

The bad reason to add tracking is FOMO. 'What if we need this data later?' Nine times out of ten you won't. And if you instrument everything, you end up with 47 custom events in Mixpanel, a dashboard nobody reads, and a vague sense that you're a very data-driven company. We've been there. It's not worth it.

One rule that's helped us: for every event you add, you need to define what action you'd take based on the data. If you can't answer 'if this number is X, I'll do Y', don't track it. This filter eliminates about 80% of the 'wouldn't it be interesting' tracking instincts.

For every event you add, define what action you'd take based on the data. If you can't answer that, don't add the event.

The Privacy and Performance Trade-offs Nobody Talks About

Every analytics script you add slows your site down and potentially pisses off privacy-conscious users. This is a real trade-off, not a theoretical one. We had a customer email us once to say they'd blocked our entire domain because of 'all the trackers' — it was just Google Analytics, but the trust damage was done.

Some practical decisions we've made: We don't use Google Analytics anymore. The data quality has gotten worse, the setup is more complex with GA4, and the privacy optics are bad for developer-facing products. We use Plausible for simple traffic stats — it's lightweight, privacy-friendly, and the numbers are actually accurate because it doesn't get blocked by uBlock. For product analytics, Posthog self-hosted if you have the infra, cloud if you don't.

On the performance side: load analytics scripts after the page is interactive, not in the critical path. Use Next.js's Script component with strategy='afterInteractive' or 'lazyOnload' for anything that isn't critical. Your Core Web Vitals will thank you, and users on slow connections won't hate you.

// In your layout.tsx — load analytics after the page is interactive
import Script from 'next/script'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        
        {/* Plausible — lightweight, privacy-friendly traffic analytics */}
        <Script
          defer
          data-domain={process.env.NEXT_PUBLIC_DOMAIN}
          src="https://plausible.io/js/script.js"
          strategy="afterInteractive"
        />
        
        {/* Don't load analytics in development */}
        {process.env.NODE_ENV === 'production' && (
          <Script
            src="/analytics-init.js" // your posthog init script
            strategy="lazyOnload"
          />
        )}
      </body>
    </html>
  )
}

The Weekly Review That Takes 15 Minutes

Here's our actual Monday morning routine. Coffee. Open the following in order: Sentry (any new errors this week?), Plausible (traffic up or down vs. last week, which sources), our retention query (is it going up or down), Stripe dashboard (MRR, new subscribers, churned subscribers). Write three numbers in a Notion doc: signups this week, activation rate, current MRR. Compare to last week. If any number moved significantly, spend 15 minutes figuring out why before doing anything else.

That's it. The whole thing takes 15-20 minutes. It keeps you honest without turning into a full-time job. If you find yourself spending two hours on analytics every week, you're either very early stage and need to be talking to users instead, or you're avoiding building things.

Most of our templates at peal.dev come with this kind of minimal analytics setup already wired in — Posthog initialization, Sentry config, and the basic event tracking for signups and upgrades — so you can skip the plumbing and focus on the thing that matters: what the numbers are actually telling you about your product.

Analytics should take up about 5% of your week, not 50%. If you're spending more time measuring than building or talking to users, something has gone wrong.

Start with retention, instrument the minimum, and add more only when you have a specific question. The goal isn't to have a beautiful dashboard. The goal is to know when something is broken or not working, and fix it. Everything else is noise.

Newsletter

Liked this post? There's more where it came from.

Dev guides, honest build stories, and the occasional 2am debugging confession — straight to your inbox. No spam, unsubscribe anytime.

Browse templates
Written by humansWeekly dropsSubscriber perks

Join the Discord

Ask questions, share builds, get help from founders