Turning Product Analytics into Actionable Insights

Learn how to transform raw analytics data into product decisions by defining KPIs, building dashboards, and establishing analysis workflows for mobile apps.

business7 min readBy Klivvr Engineering
Share:

Collecting analytics data is easy. Making decisions based on that data is hard. Many product teams drown in dashboards full of vanity metrics while struggling to answer the questions that actually matter: Why are users churning? Which features drive retention? Where does the onboarding funnel break? The gap between data collection and actionable insight is where most analytics investments fail to deliver value.

This article covers how to transform the raw event data collected by KlivvrAnalyticsKit into product insights that drive meaningful decisions.

Defining Metrics That Matter

The first step is ruthless prioritization of what you measure. Most apps track hundreds of events but only a handful actually inform decisions. The North Star metric framework helps focus your analytics on what matters.

// Define your metric hierarchy in code
struct MetricFramework {
    // North Star: The single metric that best captures the value you deliver
    let northStarMetric: MetricDefinition
 
    // Input metrics: Leading indicators that drive the North Star
    let inputMetrics: [MetricDefinition]
 
    // Health metrics: Guardrails that ensure you are not breaking things
    let healthMetrics: [MetricDefinition]
}
 
struct MetricDefinition {
    let name: String
    let description: String
    let eventName: String
    let calculation: CalculationType
    let segmentBy: [String]
 
    enum CalculationType {
        case count
        case uniqueUsers
        case sum(property: String)
        case average(property: String)
        case ratio(numeratorEvent: String, denominatorEvent: String)
        case retention(cohortEvent: String, returnEvent: String, window: Int)
    }
}
 
// Example: E-commerce app metric framework
let ecommerceMetrics = MetricFramework(
    northStarMetric: MetricDefinition(
        name: "Weekly Purchasing Users",
        description: "Unique users who complete at least one purchase per week",
        eventName: "purchase_completed",
        calculation: .uniqueUsers,
        segmentBy: ["platform", "user_segment", "acquisition_source"]
    ),
    inputMetrics: [
        MetricDefinition(
            name: "Product Discovery Rate",
            description: "Ratio of users who view products to total active users",
            eventName: "product_viewed",
            calculation: .ratio(
                numeratorEvent: "product_viewed",
                denominatorEvent: "session_started"
            ),
            segmentBy: ["category"]
        ),
        MetricDefinition(
            name: "Add to Cart Rate",
            description: "Ratio of product views that result in an add-to-cart action",
            eventName: "added_to_cart",
            calculation: .ratio(
                numeratorEvent: "added_to_cart",
                denominatorEvent: "product_viewed"
            ),
            segmentBy: ["category", "price_range"]
        ),
        MetricDefinition(
            name: "Checkout Completion Rate",
            description: "Ratio of cart views that result in a completed purchase",
            eventName: "purchase_completed",
            calculation: .ratio(
                numeratorEvent: "purchase_completed",
                denominatorEvent: "cart_viewed"
            ),
            segmentBy: ["payment_method"]
        )
    ],
    healthMetrics: [
        MetricDefinition(
            name: "Crash-Free Session Rate",
            description: "Percentage of sessions without a crash",
            eventName: "session_ended",
            calculation: .ratio(
                numeratorEvent: "session_ended_clean",
                denominatorEvent: "session_started"
            ),
            segmentBy: ["os_version", "device_model"]
        ),
        MetricDefinition(
            name: "App Load Time P95",
            description: "95th percentile app launch time",
            eventName: "app_launched",
            calculation: .average(property: "load_time_ms"),
            segmentBy: ["launch_type"]
        )
    ]
)

This hierarchy keeps your team focused. The North Star tells you if the business is healthy. Input metrics tell you what levers to pull. Health metrics tell you if something is broken.

Funnel Analysis in Practice

Funnel analysis reveals where users drop off in multi-step flows. The key is defining clean funnel stages with the right events and tracking them consistently.

// Funnel definition and tracking
struct FunnelDefinition {
    let name: String
    let steps: [FunnelStep]
 
    struct FunnelStep {
        let name: String
        let eventName: String
        let filter: [String: Any]?
    }
}
 
// Onboarding funnel
let onboardingFunnel = FunnelDefinition(
    name: "User Onboarding",
    steps: [
        FunnelStep(name: "App Opened", eventName: "app_launched", filter: ["is_first_launch": true]),
        FunnelStep(name: "Welcome Screen", eventName: "screen_viewed", filter: ["screen_name": "welcome"]),
        FunnelStep(name: "Sign Up Started", eventName: "sign_up_started", filter: nil),
        FunnelStep(name: "Sign Up Completed", eventName: "sign_up_completed", filter: nil),
        FunnelStep(name: "Profile Setup", eventName: "profile_setup_completed", filter: nil),
        FunnelStep(name: "First Action", eventName: "feature_used", filter: nil)
    ]
)
 
// Track funnel progression
extension KlivvrAnalytics {
    func trackFunnelStep(funnel: String, step: String, properties: [String: Any] = [:]) {
        var allProperties = properties
        allProperties["funnel_name"] = funnel
        allProperties["funnel_step"] = step
        allProperties["funnel_timestamp"] = ISO8601DateFormatter().string(from: Date())
        track("funnel_step_completed", properties: allProperties)
    }
}
 
// Usage
KlivvrAnalytics.shared.trackFunnelStep(
    funnel: "onboarding",
    step: "sign_up_completed",
    properties: ["method": "apple_sign_in"]
)

When analyzing funnels, always segment by user attributes. A funnel that shows a 60% overall completion rate might hide that new users from paid ads complete at 40% while organic users complete at 80%. The aggregate hides the insight.

Cohort Analysis and Retention

Retention is the most important metric for any mobile app. Cohort analysis tracks groups of users who started using the app in the same period and measures how many return over time.

// Retention event tracking
struct RetentionTracker {
    let analytics: KlivvrAnalytics
 
    // Track the activation event that defines a cohort
    func trackActivation(userId: String, cohortDate: Date, source: String) {
        analytics.track("user_activated", properties: [
            "user_id": userId,
            "cohort_date": formatDate(cohortDate),
            "cohort_week": weekNumber(cohortDate),
            "acquisition_source": source
        ])
    }
 
    // Track return visits
    func trackReturn(userId: String, originalCohortDate: Date) {
        let daysSinceActivation = Calendar.current.dateComponents(
            [.day],
            from: originalCohortDate,
            to: Date()
        ).day ?? 0
 
        analytics.track("user_returned", properties: [
            "user_id": userId,
            "cohort_date": formatDate(originalCohortDate),
            "days_since_activation": daysSinceActivation,
            "return_week": daysSinceActivation / 7
        ])
    }
 
    private func formatDate(_ date: Date) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter.string(from: date)
    }
 
    private func weekNumber(_ date: Date) -> Int {
        Calendar.current.component(.weekOfYear, from: date)
    }
}

The insight from cohort analysis is not just the retention curve itself, but how it changes across cohorts. If your Week 4 retention improved from 15% to 22% after launching a new onboarding flow, that is a clear signal that the change worked.

Segmentation for Deeper Insights

Averages lie. Segments reveal truth. Every metric should be viewed through multiple segmentation lenses to uncover hidden patterns.

// User segmentation engine
struct UserSegmentManager {
    enum Segment: String, CaseIterable {
        case powerUser = "power_user"         // Top 10% by engagement
        case regularUser = "regular_user"     // Middle 60%
        case casualUser = "casual_user"       // Bottom 30%
        case newUser = "new_user"             // First 7 days
        case reactivatedUser = "reactivated"  // Returned after 30+ days inactive
    }
 
    func computeSegment(for userActivity: UserActivity) -> Segment {
        if userActivity.daysSinceFirstOpen <= 7 {
            return .newUser
        }
        if userActivity.daysSinceLastActive > 30 && userActivity.isActiveToday {
            return .reactivatedUser
        }
 
        let weeklySessionCount = userActivity.sessionsLastWeek
        if weeklySessionCount >= 10 {
            return .powerUser
        } else if weeklySessionCount >= 3 {
            return .regularUser
        } else {
            return .casualUser
        }
    }
 
    // Attach segment to analytics events
    func enrichWithSegment(_ event: inout AnalyticsEvent, userActivity: UserActivity) {
        let segment = computeSegment(for: userActivity)
        event.properties["user_segment"] = segment.rawValue
    }
}
 
struct UserActivity {
    let daysSinceFirstOpen: Int
    let daysSinceLastActive: Int
    let sessionsLastWeek: Int
    let isActiveToday: Bool
    let lifetimePurchases: Int
    let featuresUsed: Set<String>
}

From Data to Decisions: The Analysis Workflow

Having the right data and the right metrics is necessary but not sufficient. You need a disciplined workflow for turning data into decisions.

The weekly product analytics review should follow a consistent format: start with the North Star metric trend, then review input metrics for anomalies, then deep-dive into one specific question. Each review should end with a decision or an experiment to run. If a review ends with "interesting, let's keep watching," it was not actionable.

// Automated weekly digest generation
struct WeeklyDigestGenerator {
    let metricsService: MetricsService
 
    func generateDigest() async -> WeeklyDigest {
        let thisWeek = DateInterval.lastWeek
        let lastWeek = DateInterval.weekBefore(thisWeek)
 
        async let currentNorthStar = metricsService.compute(
            metric: ecommerceMetrics.northStarMetric,
            period: thisWeek
        )
        async let previousNorthStar = metricsService.compute(
            metric: ecommerceMetrics.northStarMetric,
            period: lastWeek
        )
 
        let current = await currentNorthStar
        let previous = await previousNorthStar
 
        let percentChange = ((current - previous) / previous) * 100
 
        return WeeklyDigest(
            northStarValue: current,
            northStarChange: percentChange,
            topInsight: generateInsight(current: current, previous: previous),
            anomalies: await detectAnomalies(),
            recommendedActions: generateRecommendations(percentChange: percentChange)
        )
    }
 
    private func generateInsight(current: Double, previous: Double) -> String {
        if current > previous * 1.1 {
            return "North Star metric grew 10%+. Investigate what drove the increase."
        } else if current < previous * 0.9 {
            return "North Star metric declined 10%+. Immediate investigation needed."
        }
        return "North Star metric is stable week-over-week."
    }
}

Practical Tips

Start with five core events and expand from there rather than tracking everything on day one. Build dashboards around questions, not around events. Every dashboard should answer a specific product question. Set up automated alerts for metric anomalies so you catch issues before your weekly review. Use annotations on your charts to mark releases, campaigns, and experiments so you can correlate changes. Share analytics access broadly across the organization -- data hoarding kills data culture.

Conclusion

The value of analytics is not in the data you collect but in the decisions you make. By defining focused metric hierarchies, building actionable funnels, analyzing cohort retention, segmenting users, and establishing disciplined analysis workflows, you transform KlivvrAnalyticsKit's event stream into a product decision engine. The best analytics implementations are not the ones with the most data -- they are the ones where every tracked event exists because it answers a specific question that drives a specific decision.

Related Articles

business

Ensuring Data Quality in Mobile Analytics

Establish data quality practices for mobile analytics, including validation, monitoring, testing, and governance to maintain trustworthy analytics data.

7 min read
business

Unified Analytics Strategy Across Platforms

Develop a cohesive analytics strategy that spans iOS, Android, web, and backend platforms, ensuring consistent measurement and cross-platform user journeys.

7 min read