Skip to main content

SaaS Analytics

Analytics implementation guide for SaaS businesses, covering product analytics, trial tracking, and subscription metrics.

SaaS Analytics Framework

Key Metrics to Track

| Category | Metrics | Why It Matters | |----------|---------|----------------| | Acquisition | MQL, SQL, Trial starts | Pipeline health | | Activation | First value moment, Feature adoption | User success | | Retention | DAU/MAU, Churn rate | Product stickiness | | Revenue | MRR, LTV, Expansion | Business health | | Referral | NPS, Invites sent | Growth potential |

The SaaS Funnel

┌─────────────────────────────────────────────────────────┐
│                    SaaS Analytics Funnel                │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Website Visit      │  Trial Start    │  Activation     │
│  ─────────────────────────────────────────────────────  │
│  • Page views       │  • Sign up      │  • First key   │
│  • Demo request     │  • Plan select  │    action      │
│  • Pricing view     │  • Verification │  • Aha moment  │
│         │                   │                 │         │
│         ▼                   ▼                 ▼         │
│  Conversion         │  Paid Conversion │ Retention      │
│  ─────────────────────────────────────────────────────  │
│  • Purchase         │  • Subscription  │  • Feature use │
│  • Plan selection   │  • Payment       │  • Renewal     │
│  • Contract         │  • Upgrade       │  • Expansion   │
│                                                         │
└─────────────────────────────────────────────────────────┘

GA4 Implementation

Event Schema

// User signs up for trial
dataLayer.push({
  event: 'sign_up',
  method: 'email',
  user_id: 'user_123',
  plan_type: 'free_trial',
  plan_tier: 'professional'
});

// User completes activation step
dataLayer.push({
  event: 'tutorial_complete',
  tutorial_name: 'onboarding',
  step_number: 3,
  step_name: 'create_first_project'
});

// Feature usage
dataLayer.push({
  event: 'feature_use',
  feature_name: 'report_builder',
  feature_category: 'analytics',
  usage_count: 1
});

// Subscription purchase
dataLayer.push({
  event: 'purchase',
  transaction_id: 'sub_123',
  value: 99.00,
  currency: 'USD',
  items: [{
    item_id: 'plan_professional',
    item_name: 'Professional Plan',
    item_category: 'subscription',
    price: 99.00,
    quantity: 1
  }],
  subscription_type: 'monthly',
  trial_converted: true
});

Custom Dimensions

Set up these user properties in GA4:

| User Property | Scope | Example Values | |---------------|-------|----------------| | account_type | User | free, trial, paid | | plan_tier | User | starter, professional, enterprise | | company_size | User | 1-10, 11-50, 51-200, 200+ | | industry | User | technology, finance, healthcare | | signup_date | User | 2024-01-15 | | trial_end_date | User | 2024-01-29 |

Event Dimensions

| Parameter | Events | Purpose | |-----------|--------|---------| | feature_name | feature_use | Feature adoption tracking | | workflow_step | workflow_* | Funnel analysis | | error_type | error | Issue identification |

Product Analytics Events

Onboarding Funnel

// Step 1: Account created
dataLayer.push({
  event: 'onboarding_start',
  step: 1,
  step_name: 'account_created'
});

// Step 2: Profile completed
dataLayer.push({
  event: 'onboarding_progress',
  step: 2,
  step_name: 'profile_completed'
});

// Step 3: First project created
dataLayer.push({
  event: 'onboarding_progress',
  step: 3,
  step_name: 'first_project'
});

// Step 4: Team member invited
dataLayer.push({
  event: 'onboarding_progress',
  step: 4,
  step_name: 'team_invited'
});

// Completion
dataLayer.push({
  event: 'onboarding_complete',
  steps_completed: 4,
  time_to_complete_seconds: 1800
});

Feature Adoption

// Generic feature tracking
function trackFeatureUse(featureName, category, metadata = {}) {
  dataLayer.push({
    event: 'feature_use',
    feature_name: featureName,
    feature_category: category,
    ...metadata
  });
}

// Examples
trackFeatureUse('create_report', 'analytics');
trackFeatureUse('invite_team_member', 'collaboration');
trackFeatureUse('api_integration', 'developer', { api_type: 'rest' });
trackFeatureUse('export_data', 'data', { format: 'csv', rows: 1500 });

Activation Tracking

Define your activation metric (the "Aha moment"):

// Example: User activated when they create 3 reports
const ACTIVATION_THRESHOLD = 3;

function checkActivation(reportCount) {
  if (reportCount >= ACTIVATION_THRESHOLD && !userActivated) {
    dataLayer.push({
      event: 'user_activated',
      activation_trigger: 'report_creation',
      days_to_activation: daysSinceSignup(),
      reports_at_activation: reportCount
    });
  }
}

Subscription Analytics

MRR Events

// New subscription
dataLayer.push({
  event: 'subscription_started',
  subscription_id: 'sub_abc123',
  plan_tier: 'professional',
  billing_period: 'monthly',
  mrr: 99.00,
  is_trial_conversion: true
});

// Upgrade
dataLayer.push({
  event: 'subscription_upgraded',
  subscription_id: 'sub_abc123',
  previous_plan: 'starter',
  new_plan: 'professional',
  previous_mrr: 29.00,
  new_mrr: 99.00,
  mrr_change: 70.00
});

// Downgrade
dataLayer.push({
  event: 'subscription_downgraded',
  subscription_id: 'sub_abc123',
  previous_plan: 'professional',
  new_plan: 'starter',
  previous_mrr: 99.00,
  new_mrr: 29.00,
  mrr_change: -70.00
});

// Churn
dataLayer.push({
  event: 'subscription_cancelled',
  subscription_id: 'sub_abc123',
  plan_tier: 'professional',
  mrr_lost: 99.00,
  cancellation_reason: 'too_expensive',
  months_as_customer: 8
});

Revenue Attribution

Connect marketing spend to subscription revenue:

// Include attribution data with subscription
dataLayer.push({
  event: 'subscription_started',
  // ... subscription details
  attribution: {
    first_touch_source: 'google',
    first_touch_medium: 'cpc',
    first_touch_campaign: 'brand_search',
    last_touch_source: 'direct',
    signup_to_paid_days: 14
  }
});

BigQuery Analysis

Trial Conversion Analysis

-- Trial to paid conversion by source
WITH trials AS (
  SELECT
    user_pseudo_id,
    user_id,
    traffic_source.source,
    traffic_source.medium,
    MIN(event_timestamp) as trial_start
  FROM `project.analytics.events_*`
  WHERE event_name = 'sign_up'
    AND event_params.key = 'plan_type'
    AND event_params.value.string_value = 'free_trial'
  GROUP BY 1, 2, 3, 4
),
conversions AS (
  SELECT
    user_id,
    MIN(event_timestamp) as conversion_time
  FROM `project.analytics.events_*`
  WHERE event_name = 'subscription_started'
  GROUP BY 1
)
SELECT
  t.source,
  t.medium,
  COUNT(DISTINCT t.user_id) as trials,
  COUNT(DISTINCT c.user_id) as conversions,
  SAFE_DIVIDE(COUNT(DISTINCT c.user_id), COUNT(DISTINCT t.user_id)) as conversion_rate
FROM trials t
LEFT JOIN conversions c ON t.user_id = c.user_id
GROUP BY 1, 2
ORDER BY trials DESC

Feature Adoption Cohorts

-- Feature adoption by signup cohort
WITH user_cohorts AS (
  SELECT
    user_id,
    DATE(TIMESTAMP_MICROS(MIN(event_timestamp))) as signup_date
  FROM `project.analytics.events_*`
  WHERE event_name = 'sign_up'
  GROUP BY 1
),
feature_usage AS (
  SELECT
    user_id,
    event_params.value.string_value as feature_name,
    DATE(TIMESTAMP_MICROS(MIN(event_timestamp))) as first_use_date
  FROM `project.analytics.events_*`
  WHERE event_name = 'feature_use'
    AND event_params.key = 'feature_name'
  GROUP BY 1, 2
)
SELECT
  DATE_TRUNC(uc.signup_date, WEEK) as signup_week,
  fu.feature_name,
  COUNT(DISTINCT uc.user_id) as users,
  COUNT(DISTINCT fu.user_id) as feature_users,
  SAFE_DIVIDE(COUNT(DISTINCT fu.user_id), COUNT(DISTINCT uc.user_id)) as adoption_rate
FROM user_cohorts uc
LEFT JOIN feature_usage fu ON uc.user_id = fu.user_id
GROUP BY 1, 2
ORDER BY 1 DESC, adoption_rate DESC

LTV Calculation

-- Calculate customer lifetime value
WITH customer_revenue AS (
  SELECT
    user_id,
    DATE(TIMESTAMP_MICROS(MIN(event_timestamp))) as first_purchase,
    DATE(TIMESTAMP_MICROS(MAX(event_timestamp))) as last_purchase,
    SUM(event_params.value.double_value) as total_revenue,
    COUNT(*) as transactions
  FROM `project.analytics.events_*`
  WHERE event_name = 'purchase'
    AND event_params.key = 'value'
  GROUP BY 1
)
SELECT
  DATE_TRUNC(first_purchase, MONTH) as cohort_month,
  COUNT(DISTINCT user_id) as customers,
  AVG(total_revenue) as avg_ltv,
  AVG(DATE_DIFF(last_purchase, first_purchase, DAY)) as avg_customer_days
FROM customer_revenue
GROUP BY 1
ORDER BY 1 DESC

Dashboards

Key SaaS Metrics Dashboard

| Metric | Calculation | Target | |--------|-------------|--------| | Trial Starts | Count of sign_up events | Increasing | | Trial-to-Paid | Conversions / Trials | 15-25% | | Time to Activation | Avg days to activated | < 3 days | | Feature Adoption | Users using key feature / Total users | 60%+ | | Monthly Active Users | Unique users with events | Increasing | | Net MRR Growth | New + Expansion - Churn | Positive |

Looker Studio Components

  1. Acquisition Overview - Traffic sources, trial signups
  2. Activation Funnel - Onboarding completion rates
  3. Product Engagement - Feature usage, DAU/MAU
  4. Revenue Metrics - MRR, LTV, churn
  5. Cohort Analysis - Retention by signup date

Integration Points

Connect to Your Stack

| Tool | Integration | Data Flow | |------|-------------|-----------| | Stripe | Webhook → Server → GA4 | Subscription events | | Segment | CDP | Unified user tracking | | Mixpanel | Parallel tracking | Product analytics | | Amplitude | Parallel tracking | Product analytics | | HubSpot | GA4 events → CRM | Lead scoring |

Server-Side Events

For subscription events, use server-side:

// Server-side (Node.js example)
const measurement_id = 'G-XXXXXXXXXX';
const api_secret = 'your_api_secret';

fetch(`https://www.google-analytics.com/mp/collect?measurement_id=${measurement_id}&api_secret=${api_secret}`, {
  method: 'POST',
  body: JSON.stringify({
    client_id: 'server_generated_id',
    user_id: 'user_123',
    events: [{
      name: 'subscription_started',
      params: {
        subscription_id: 'sub_abc',
        plan_tier: 'professional',
        mrr: 99.00
      }
    }]
  })
});

Previous: Debug & Validation Next: B2B Lead Gen