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.
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
Debugging Analytics: Ensuring Accurate Event Tracking
Master techniques for debugging analytics implementations in iOS apps, from real-time event inspection to automated validation and production monitoring.
Ensuring Data Quality in Mobile Analytics
Establish data quality practices for mobile analytics, including validation, monitoring, testing, and governance to maintain trustworthy analytics data.
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.