
Funnel Analysis
- 3 installs
- 3 repo stars
- Updated December 23, 2025
- liangdabiao/claude-data-analysis-ultra
Helps with ai & agent building tasks.
About
funnel-analysis is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- funnel-analysis
- AI & Agent Building
- AI-coding skill
Funnel Analysis by the numbers
- 3 all-time installs (skills.sh)
- Ranked #13,657 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/liangdabiao/claude-data-analysis-ultra --skill funnel-analysisAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| repo stars | ★ 3 |
| Last updated | December 23, 2025 |
| Repository | liangdabiao/claude-data-analysis-ultra ↗ |
What it does
Helps with ai & agent building tasks.
Files
Funnel Analysis Skill
Analyze user behavior through multi-step conversion funnels to identify bottlenecks and optimization opportunities in marketing campaigns, user journeys, and business processes.
Quick Start
This skill helps you: 1. Build conversion funnels from multi-step user data 2. Calculate conversion rates between each step 3. Perform segmentation analysis by different user attributes 4. Create interactive visualizations with Plotly 5. Generate business insights and optimization recommendations
When to Use
- Marketing campaign analysis (promotion → purchase)
- User onboarding flow analysis
- Website conversion funnel optimization
- App user journey analysis
- Sales pipeline analysis
- Lead nurturing process analysis
Key Requirements
Install required packages:
pip install pandas plotly matplotlib numpy seabornCore Workflow
1. Data Preparation
Your data should include:
- User journey steps (clicks, page views, actions)
- User identifiers (customer_id, user_id, etc.)
- Timestamps or step indicators
- Optional: user attributes for segmentation (gender, device, location)
2. Analysis Process
1. Load and merge user journey data 2. Define funnel steps and calculate metrics 3. Perform segmentations (by device, gender, etc.) 4. Create visualizations 5. Generate insights and recommendations
3. Output Deliverables
- Funnel visualization charts
- Conversion rate tables
- Segmented analysis reports
- Optimization recommendations
Example Usage Scenarios
E-commerce Purchase Funnel
# Steps: Promotion → Search → Product View → Add to Cart → Purchase
# Analyze by device type and customer segmentUser Registration Funnel
# Steps: Landing Page → Sign Up → Email Verification → Profile Complete
# Identify where users drop off mostContent Consumption Funnel
# Steps: Article View → Comment → Share → Subscribe
# Measure engagement conversion ratesCommon Analysis Patterns
1. Bottleneck Identification: Find steps with highest drop-off rates 2. Segment Comparison: Compare conversion across user groups 3. Temporal Analysis: Track conversion over time 4. A/B Testing: Compare different funnel variations 5. Optimization Impact: Measure changes before/after improvements
Integration Examples
See examples/ directory for:
basic_funnel.py- Simple funnel analysissegmented_funnel.py- Advanced segmentation analysis- Sample datasets for testing
Best Practices
- Ensure data quality and consistency
- Define clear funnel steps
- Consider user journey time windows
- Validate statistical significance
- Focus on actionable insights
<!DOCTYPE html>
<html>
<head>
<title>Funnel Analysis Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
.metrics { margin: 20px 0; }
.insights { background-color: #f9f9f9; padding: 20px; border-radius: 5px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<div class="header">
<h1>Funnel Analysis Report</h1>
<p>Generated on 2025-12-19 21:20:13</p>
</div>
<div class="metrics">
<h2>Key Metrics</h2>
<ul>
<li><strong>Total Conversion Rate:</strong> 0.2%</li>
<li><strong>Total Drop-off Rate:</strong> 99.8%</li>
<li><strong>Biggest Drop-off:</strong> Purchase</li>
</ul>
</div>
<div class="insights">
<h2>Key Insights</h2>
<ul>
<li>❗ Critical: Overall conversion rate is below 1%, requires immediate attention</li><li>🎯 Biggest drop-off: Purchase (92.9% loss)</li><li>📊 Search has moderate conversion (49.8%)</li><li>📊 Product View has moderate conversion (30.2%)</li><li>📉 Add to Cart has very low conversion (15.9%)</li><li>📉 Purchase has very low conversion (7.1%)</li>
</ul>
</div>
<div>
<h2>Funnel Details</h2>
<table>
<tr>
<th>Step</th>
<th>Users</th>
<th>Conversion Rate</th>
<th>Drop-off Rate</th>
</tr>
<tr>
<td>Homepage</td>
<td>10,000</td>
<td>100.0%</td>
<td>0.0%</td>
</tr>
<tr>
<td>Search</td>
<td>4,978</td>
<td>49.8%</td>
<td>50.2%</td>
</tr>
<tr>
<td>Product View</td>
<td>1,505</td>
<td>30.2%</td>
<td>69.8%</td>
</tr>
<tr>
<td>Add to Cart</td>
<td>239</td>
<td>15.9%</td>
<td>84.1%</td>
</tr>
<tr>
<td>Purchase</td>
<td>17</td>
<td>7.1%</td>
<td>92.9%</td>
</tr>
</table>
</div>
</body>
</html>
"""
Basic Funnel Analysis Example
This example demonstrates how to use the Funnel Analysis skill
to analyze a simple e-commerce conversion funnel.
"""
import pandas as pd
import numpy as np
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from scripts.funnel_analyzer import FunnelAnalyzer
from scripts.visualizer import FunnelVisualizer
def create_sample_data():
"""
Create sample e-commerce funnel data.
"""
np.random.seed(42)
n_users = 10000
# Generate user data
data = {
'user_id': range(1, n_users + 1),
'device': np.random.choice(['Mobile', 'Desktop'], n_users, p=[0.6, 0.4]),
'gender': np.random.choice(['Male', 'Female'], n_users, p=[0.55, 0.45]),
'homepage': True, # All users visit homepage
'search': np.random.choice([True, False], n_users, p=[0.5, 0.5]),
'product_view': np.random.choice([True, False], n_users, p=[0.3, 0.7]),
'add_to_cart': np.random.choice([True, False], n_users, p=[0.15, 0.85]),
'purchase': np.random.choice([True, False], n_users, p=[0.05, 0.95])
}
# Create dependencies: users must complete previous steps to reach later steps
df = pd.DataFrame(data)
# Apply logical dependencies
for i in range(len(df)):
if not df.loc[i, 'search']:
df.loc[i, 'product_view'] = False
df.loc[i, 'add_to_cart'] = False
df.loc[i, 'purchase'] = False
elif not df.loc[i, 'product_view']:
df.loc[i, 'add_to_cart'] = False
df.loc[i, 'purchase'] = False
elif not df.loc[i, 'add_to_cart']:
df.loc[i, 'purchase'] = False
return df
def main():
"""
Run basic funnel analysis example.
"""
print("=== Basic Funnel Analysis Example ===\n")
# Create sample data
print("1. Creating sample e-commerce data...")
df = create_sample_data()
print(f" Generated data for {len(df)} users")
# Initialize analyzer
analyzer = FunnelAnalyzer()
# Load data
analyzer.load_data(df, user_id_col='user_id')
# Define funnel steps
steps = ['Homepage', 'Search', 'Product View', 'Add to Cart', 'Purchase']
step_columns = ['homepage', 'search', 'product_view', 'add_to_cart', 'purchase']
analyzer.define_steps(steps, step_columns)
# Build funnel
print("\n2. Building conversion funnel...")
funnel_df = analyzer.build_funnel()
print("\nFunnel Results:")
print(funnel_df[['step', 'users', 'conversion_rate']].to_string(index=False,
formatters={'conversion_rate': '{:.1%}'.format}))
# Calculate metrics
print("\n3. Calculating key metrics...")
metrics = analyzer.calculate_metrics(funnel_df)
print(f"Overall Conversion Rate: {metrics['total_conversion_rate']:.1%}")
print(f"Total Drop-off Rate: {metrics['total_drop_off_rate']:.1%}")
if metrics['biggest_drop_off_step']:
print(f"Biggest Drop-off: {metrics['biggest_drop_off_step']} ({metrics['biggest_drop_off_rate']:.1%})")
# Generate insights
print("\n4. Generating insights...")
insights = analyzer.generate_insights(funnel_df)
print("Key Insights:")
for insight in insights:
print(f" {insight}")
# Create visualizations
print("\n5. Creating visualizations...")
visualizer = FunnelVisualizer()
# Basic funnel chart
funnel_fig = visualizer.create_basic_funnel(
funnel_df,
title="E-commerce Conversion Funnel"
)
visualizer.save_figure(funnel_fig, 'basic_funnel_chart.html', 'html')
# Conversion rate chart
conv_rate_fig = visualizer.create_conversion_rate_chart(
funnel_df,
title="Step-by-Step Conversion Rates"
)
visualizer.save_figure(conv_rate_fig, 'conversion_rates.html', 'html')
# Drop-off analysis
drop_off_fig = visualizer.create_drop_off_analysis(
funnel_df,
title="User Drop-off Analysis"
)
visualizer.save_figure(drop_off_fig, 'drop_off_analysis.html', 'html')
# Comprehensive dashboard
dashboard_fig = visualizer.create_comprehensive_dashboard(
funnel_df,
title="E-commerce Funnel Dashboard"
)
visualizer.save_figure(dashboard_fig, 'funnel_dashboard.html', 'html')
# Export detailed report
print("\n6. Exporting detailed report...")
report_path = analyzer.export_report(funnel_df, filename='basic_funnel_report.html')
print(f"\n=== Analysis Complete ===")
print(f"Generated files:")
print(f" - basic_funnel_chart.html")
print(f" - conversion_rates.html")
print(f" - drop_off_analysis.html")
print(f" - funnel_dashboard.html")
print(f" - basic_funnel_report.html")
if __name__ == "__main__":
main()Sample Data for Funnel Analysis
This directory contains sample datasets to help you understand how to structure your data for funnel analysis.
Data Structure Requirements
For effective funnel analysis, your data should include:
Required Columns
- User Identifier: Unique ID for each user (e.g.,
user_id,customer_id) - Step Indicators: Boolean flags or timestamps for each funnel step
Optional Columns (for segmentation)
- Device Type:
device,platform,client_type - User Segment:
segment,user_type,customer_tier - Demographics:
gender,age_group,location - Temporal Data:
date,timestamp,cohort
Example Data Formats
E-commerce Funnel
user_id,device,segment,homepage,search,product_view,add_to_cart,purchase
1001,Mobile,New User,True,True,False,False,False
1002,Desktop,Returning User,True,True,True,True,True
1003,Mobile,VIP User,True,True,True,True,FalseMarketing Funnel
user_id,traffic_source,campaign,ad_click,landing_page,sign_up,email_verify
1001,Google,campaign_a,True,True,True,False
1002,Facebook,campaign_b,True,False,False,False
1003,Direct,organic,True,True,True,TrueUser Onboarding Funnel
user_id,sign_up_date,profile_complete,tutorial_start,tutorial_complete,first_action
1001,2024-01-15,True,True,True,True
1002,2024-01-16,True,False,False,False
1003,2024-01-17,True,True,True,FalseKey Considerations
1. Data Consistency: Ensure consistent user identification across all steps 2. Step Order: Maintain logical order in your funnel steps 3. Missing Values: Handle missing data appropriately (usually means user didn't reach that step) 4. Time Windows: Consider appropriate time frames for user journeys 5. Sample Size: Ensure adequate sample sizes for reliable analysis
Data Validation Checklist
- [ ] Unique user identifiers for all records
- [ ] Clear step definitions and indicators
- [ ] Consistent data types across columns
- [ ] Appropriate handling of missing values
- [ ] Sufficient sample size for each segment
- [ ] Logical flow between funnel steps
<!DOCTYPE html>
<html>
<head>
<title>Funnel Analysis Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
.metrics { margin: 20px 0; }
.insights { background-color: #f9f9f9; padding: 20px; border-radius: 5px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<div class="header">
<h1>Funnel Analysis Report</h1>
<p>Generated on 2025-12-19 21:20:33</p>
</div>
<div class="metrics">
<h2>Key Metrics</h2>
<ul>
<li><strong>Total Conversion Rate:</strong> 100.0%</li>
<li><strong>Total Drop-off Rate:</strong> 0.0%</li>
<li><strong>Biggest Drop-off:</strong> None</li>
</ul>
</div>
<div class="insights">
<h2>Key Insights</h2>
<ul>
<li>✓ Overall conversion rate is 100.0%</li>
</ul>
</div>
<div>
<h2>Funnel Details</h2>
<table>
<tr>
<th>Step</th>
<th>Users</th>
<th>Conversion Rate</th>
<th>Drop-off Rate</th>
</tr>
<tr>
<td>Homepage</td>
<td>15,000</td>
<td>100.0%</td>
<td>0.0%</td>
</tr>
<tr>
<td>Search</td>
<td>15,000</td>
<td>100.0%</td>
<td>0.0%</td>
</tr>
<tr>
<td>Product View</td>
<td>15,000</td>
<td>100.0%</td>
<td>0.0%</td>
</tr>
<tr>
<td>Add to Cart</td>
<td>15,000</td>
<td>100.0%</td>
<td>0.0%</td>
</tr>
<tr>
<td>Purchase</td>
<td>15,000</td>
<td>100.0%</td>
<td>0.0%</td>
</tr>
</table>
</div>
</body>
</html>
"""
Segmented Funnel Analysis Example
This example demonstrates advanced funnel analysis with segmentation,
showing how different user groups behave differently in the conversion funnel.
"""
import pandas as pd
import numpy as np
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from scripts.funnel_analyzer import FunnelAnalyzer
from scripts.visualizer import FunnelVisualizer
def create_segmented_data():
"""
Create sample e-commerce funnel data with segmentation.
"""
np.random.seed(42)
n_users = 15000
# Generate user segments with different behaviors
segments = []
devices = []
genders = []
for i in range(n_users):
# Create segments with different characteristics
segment_prob = np.random.random()
if segment_prob < 0.3:
segments.append('New User')
elif segment_prob < 0.7:
segments.append('Returning User')
else:
segments.append('VIP User')
devices.append(np.random.choice(['Mobile', 'Desktop'], p=[0.6, 0.4]))
genders.append(np.random.choice(['Male', 'Female'], p=[0.55, 0.45]))
# Generate funnel behavior based on segments
data = {
'user_id': range(1, n_users + 1),
'segment': segments,
'device': devices,
'gender': genders,
'homepage': True
}
df = pd.DataFrame(data)
# Generate step completion probabilities based on segment
for i, row in df.iterrows():
segment = row['segment']
if segment == 'New User':
# Lower conversion rates for new users
search_prob = 0.4
product_view_prob = 0.2
add_to_cart_prob = 0.08
purchase_prob = 0.02
elif segment == 'Returning User':
# Medium conversion rates
search_prob = 0.6
product_view_prob = 0.35
add_to_cart_prob = 0.18
purchase_prob = 0.06
else: # VIP User
# Higher conversion rates for VIP users
search_prob = 0.8
product_view_prob = 0.6
add_to_cart_prob = 0.4
purchase_prob = 0.25
# Apply segment-specific probabilities
df.loc[i, 'search'] = np.random.random() < search_prob
if df.loc[i, 'search']:
df.loc[i, 'product_view'] = np.random.random() < product_view_prob
if df.loc[i, 'product_view']:
df.loc[i, 'add_to_cart'] = np.random.random() < add_to_cart_prob
if df.loc[i, 'add_to_cart']:
df.loc[i, 'purchase'] = np.random.random() < purchase_prob
else:
df.loc[i, 'purchase'] = False
else:
df.loc[i, 'add_to_cart'] = False
df.loc[i, 'purchase'] = False
else:
df.loc[i, 'product_view'] = False
df.loc[i, 'add_to_cart'] = False
df.loc[i, 'purchase'] = False
return df
def analyze_segments(analyzer, df, segment_col):
"""
Perform detailed segment analysis.
"""
print(f"\n=== Analysis by {segment_col} ===")
# Get segmented funnels
segment_funnels = analyzer.segment_analysis(segment_col)
# Calculate metrics for each segment
segment_metrics = {}
for segment, funnel_df in segment_funnels.items():
metrics = analyzer.calculate_metrics(funnel_df)
segment_metrics[segment] = metrics
print(f"\n{segment} Segment:")
print(f" Users: {funnel_df.iloc[0]['users']:,}")
print(f" Conversion Rate: {metrics['total_conversion_rate']:.1%}")
if metrics['biggest_drop_off_step']:
print(f" Biggest Drop-off: {metrics['biggest_drop_off_step']} ({metrics['biggest_drop_off_rate']:.1%})")
return segment_funnels, segment_metrics
def create_segment_comparison_chart(segment_funnels, segment_metrics, segment_type):
"""
Create a detailed segment comparison visualization.
"""
visualizer = FunnelVisualizer()
# Create comparison chart
comparison_fig = visualizer.create_segment_comparison(
segment_funnels,
metric="total_conversion_rate",
title=f"Conversion Rate by {segment_type}"
)
visualizer.save_figure(comparison_fig, f'segment_comparison_{segment_type.lower()}.html', 'html')
# Create segmented funnel chart
segmented_funnel_fig = visualizer.create_segmented_funnel(
segment_funnels,
title=f"Funnel Comparison by {segment_type}"
)
visualizer.save_figure(segmented_funnel_fig, f'segmented_funnel_{segment_type.lower()}.html', 'html')
def main():
"""
Run segmented funnel analysis example.
"""
print("=== Segmented Funnel Analysis Example ===\n")
# Create segmented sample data
print("1. Creating segmented sample data...")
df = create_segmented_data()
print(f" Generated data for {len(df)} users")
print(f" Segments: {df['segment'].value_counts().to_dict()}")
# Initialize analyzer
analyzer = FunnelAnalyzer()
analyzer.load_data(df, user_id_col='user_id')
# Define funnel steps
steps = ['Homepage', 'Search', 'Product View', 'Add to Cart', 'Purchase']
step_columns = ['homepage', 'search', 'product_view', 'add_to_cart', 'purchase']
analyzer.define_steps(steps, step_columns)
# Overall analysis
print("\n2. Overall funnel analysis...")
overall_funnel = analyzer.build_funnel()
print("\nOverall Funnel Results:")
print(overall_funnel[['step', 'users', 'conversion_rate']].to_string(
index=False,
formatters={'conversion_rate': '{:.1%}'.format}
))
# Segment analysis
print("\n3. Segment analysis...")
# Analysis by user segment
segment_funnels, segment_metrics = analyze_segments(analyzer, df, 'segment')
create_segment_comparison_chart(segment_funnels, segment_metrics, 'User Segment')
# Analysis by device
device_funnels, device_metrics = analyze_segments(analyzer, df, 'device')
create_segment_comparison_chart(device_funnels, device_metrics, 'Device')
# Analysis by gender
gender_funnels, gender_metrics = analyze_segments(analyzer, df, 'gender')
create_segment_comparison_chart(gender_funnels, gender_metrics, 'Gender')
# Generate insights with segmentation
print("\n4. Generating segmented insights...")
insights = analyzer.generate_insights(overall_funnel, segment_funnels)
print("Key Insights:")
for insight in insights:
print(f" {insight}")
# Create comprehensive dashboard with segmentation
print("\n5. Creating comprehensive dashboard...")
visualizer = FunnelVisualizer()
dashboard_fig = visualizer.create_comprehensive_dashboard(
overall_funnel,
segment_funnels,
title="Segmented Funnel Analysis Dashboard"
)
visualizer.save_figure(dashboard_fig, 'segmented_dashboard.html', 'html')
# Export segmented report
print("\n6. Exporting segmented report...")
report_path = analyzer.export_report(
overall_funnel,
segment_funnels,
filename='segmented_funnel_report.html'
)
# Performance summary
print("\n=== Performance Summary ===")
best_segment = max(segment_metrics.items(), key=lambda x: x[1]['total_conversion_rate'])
worst_segment = min(segment_metrics.items(), key=lambda x: x[1]['total_conversion_rate'])
print(f"Best Performing Segment: {best_segment[0]} ({best_segment[1]['total_conversion_rate']:.1%})")
print(f"Worst Performing Segment: {worst_segment[0]} ({worst_segment[1]['total_conversion_rate']:.1%})")
print(f"Performance Gap: {(best_segment[1]['total_conversion_rate'] / worst_segment[1]['total_conversion_rate'] - 1):.1f}x")
print(f"\n=== Analysis Complete ===")
print(f"Generated files:")
print(f" - segment_comparison_user segment.html")
print(f" - segmented_funnel_user segment.html")
print(f" - segment_comparison_device.html")
print(f" - segmented_funnel_device.html")
print(f" - segment_comparison_gender.html")
print(f" - segmented_funnel_gender.html")
print(f" - segmented_dashboard.html")
print(f" - segmented_funnel_report.html")
if __name__ == "__main__":
main()Funnel Analysis Skill
This skill provides comprehensive funnel analysis capabilities for understanding user conversion patterns and optimizing business processes.
Overview
The Funnel Analysis Skill is designed to analyze multi-step user journeys, calculate conversion rates, and identify optimization opportunities in various business contexts including e-commerce, marketing campaigns, user onboarding, and content consumption.
Features
Core Capabilities
- Multi-step Funnel Construction: Build funnels from user journey data
- Conversion Rate Analysis: Calculate step-by-step and overall conversion rates
- Segmentation Analysis: Compare funnels across different user segments
- Interactive Visualizations: Create engaging funnel charts with Plotly
- Automated Insights: Generate actionable recommendations
Analysis Types
1. Standard Funnel Analysis: Track conversion through defined steps 2. Segmented Analysis: Compare different user groups 3. Temporal Analysis: Track changes over time 4. Cohort Analysis: Analyze behavior by user cohorts 5. A/B Test Analysis: Compare funnel variations
File Structure
funnel-analysis/
├── SKILL.md # Main skill definition
├── README.md # This file
├── examples/ # Usage examples
│ ├── basic_funnel.py # Simple funnel analysis
│ ├── segmented_funnel.py # Segmented analysis
│ └── sample_data/ # Example datasets
└── scripts/ # Utility scripts
├── funnel_analyzer.py # Core analysis functions
└── visualizer.py # Visualization utilitiesGetting Started
Prerequisites
Ensure you have these Python packages installed:
pip install pandas plotly matplotlib numpy seabornBasic Usage
1. Prepare your data with user journey steps 2. Define your funnel steps and metrics 3. Run analysis using the provided scripts 4. Visualize results with interactive charts 5. Generate insights for optimization
Data Format Requirements
Your data should include:
- User ID: Unique identifier for each user
- Step indicators: Boolean flags or timestamps for each step
- Segmentation attributes (optional): Device, gender, location, etc.
- Timestamps (optional): For temporal analysis
Examples
E-commerce Example
# Analyze: Homepage → Search → Product View → Add to Cart → Purchase
from scripts.funnel_analyzer import FunnelAnalyzer
analyzer = FunnelAnalyzer()
results = analyzer.analyze_funnel(data, steps)
analyzer.visualize(results)Marketing Campaign Example
# Track: Ad Click → Landing Page → Sign Up → First Purchase
# Compare by traffic source and device typeBest Practices
1. Data Quality
- Ensure consistent user identification
- Handle missing data appropriately
- Validate step sequences
2. Analysis Design
- Define clear, logical funnel steps
- Consider time windows for user journeys
- Account for multiple touchpoints
3. Interpretation
- Look for statistically significant patterns
- Consider business context
- Focus on actionable insights
Common Use Cases
- E-commerce: Purchase funnel optimization
- SaaS: User onboarding and activation
- Content Platforms: Engagement and conversion
- Lead Generation: Marketing campaign effectiveness
- Mobile Apps: User retention and feature adoption
Troubleshooting
Common Issues
1. Low Conversion Rates
- Check data quality and step definitions
- Verify user journey completeness
- Consider time window adjustments
2. Segment Size Disparities
- Ensure sufficient sample sizes
- Consider combining small segments
- Use statistical significance tests
3. Complex User Journeys
- Simplify funnel structure
- Consider multiple funnel paths
- Use path analysis techniques
Advanced Topics
Statistical Considerations
- Confidence intervals for conversion rates
- A/B test significance testing
- Cohort retention analysis
Extensions
- Machine learning for funnel prediction
- Real-time funnel monitoring
- Multi-channel attribution modeling
Support
For issues or questions, refer to the examples directory or modify the scripts to suit your specific needs.
"""
Funnel Analysis Core Functions
This module provides the main functionality for analyzing user conversion funnels,
including data processing, conversion rate calculations, and segmentation analysis.
"""
import pandas as pd
import numpy as np
from typing import List, Dict, Optional, Tuple
import warnings
class FunnelAnalyzer:
"""
Main class for funnel analysis.
Provides methods for building funnels from user journey data,
calculating conversion rates, and performing segmentation analysis.
"""
def __init__(self):
self.data = None
self.funnel_steps = []
self.user_id_col = 'user_id'
def load_data(self, data: pd.DataFrame, user_id_col: str = 'user_id') -> None:
"""
Load user journey data for funnel analysis.
Args:
data: DataFrame containing user journey information
user_id_col: Name of the user identifier column
"""
self.data = data.copy()
self.user_id_col = user_id_col
print(f"Loaded data with {len(data)} users and {len(data.columns)} columns")
def define_steps(self, steps: List[str], step_columns: List[str] = None) -> None:
"""
Define funnel steps for analysis.
Args:
steps: List of step names in order
step_columns: List of corresponding column names (optional)
"""
self.funnel_steps = steps
if step_columns:
self.step_columns = step_columns
else:
# Default: assume columns have same names as steps
self.step_columns = steps
print(f"Defined funnel with {len(steps)} steps: {steps}")
def build_funnel(self) -> pd.DataFrame:
"""
Build funnel data frame with user counts at each step.
Returns:
DataFrame with step names and user counts
"""
if self.data is None:
raise ValueError("No data loaded. Use load_data() first.")
if not self.funnel_steps:
raise ValueError("No steps defined. Use define_steps() first.")
funnel_data = []
for i, (step_name, step_col) in enumerate(zip(self.funnel_steps, self.step_columns)):
if step_col in self.data.columns:
# Count users who reached this step
if self.data[step_col].dtype == 'bool':
count = self.data[step_col].sum()
elif pd.api.types.is_datetime64_any_dtype(self.data[step_col]):
count = self.data[step_col].notna().sum()
else:
# Assume non-null means reached step
count = self.data[step_col].notna().sum()
funnel_data.append({
'step': step_name,
'step_order': i + 1,
'users': count,
'conversion_rate': None # Will calculate later
})
else:
warnings.warn(f"Column '{step_col}' not found in data")
funnel_df = pd.DataFrame(funnel_data)
# Calculate conversion rates
for i in range(len(funnel_df)):
if i == 0:
funnel_df.loc[i, 'conversion_rate'] = 1.0
else:
prev_users = funnel_df.loc[i-1, 'users']
curr_users = funnel_df.loc[i, 'users']
if prev_users > 0:
funnel_df.loc[i, 'conversion_rate'] = curr_users / prev_users
else:
funnel_df.loc[i, 'conversion_rate'] = 0
return funnel_df
def segment_analysis(self, segment_col: str) -> Dict[str, pd.DataFrame]:
"""
Perform funnel analysis segmented by a categorical variable.
Args:
segment_col: Column name for segmentation
Returns:
Dictionary with segment names as keys and funnel DataFrames as values
"""
if segment_col not in self.data.columns:
raise ValueError(f"Segment column '{segment_col}' not found")
segments = self.data[segment_col].unique()
segment_funnels = {}
for segment in segments:
segment_data = self.data[self.data[segment_col] == segment].copy()
# Temporarily replace data for segment
original_data = self.data
self.data = segment_data
try:
segment_funnel = self.build_funnel()
segment_funnels[str(segment)] = segment_funnel
finally:
# Restore original data
self.data = original_data
return segment_funnels
def calculate_metrics(self, funnel_df: pd.DataFrame) -> Dict[str, float]:
"""
Calculate key funnel metrics.
Args:
funnel_df: Funnel DataFrame from build_funnel()
Returns:
Dictionary with calculated metrics
"""
if len(funnel_df) == 0:
return {}
total_users_start = funnel_df.iloc[0]['users']
total_users_end = funnel_df.iloc[-1]['users']
metrics = {
'total_conversion_rate': total_users_end / total_users_start if total_users_start > 0 else 0,
'total_drop_off_rate': 1 - (total_users_end / total_users_start) if total_users_start > 0 else 0,
'biggest_drop_off_step': None,
'biggest_drop_off_rate': 0
}
# Find biggest drop-off
for i in range(1, len(funnel_df)):
prev_users = funnel_df.iloc[i-1]['users']
curr_users = funnel_df.iloc[i]['users']
if prev_users > 0:
drop_off_rate = 1 - (curr_users / prev_users)
if drop_off_rate > metrics['biggest_drop_off_rate']:
metrics['biggest_drop_off_rate'] = drop_off_rate
metrics['biggest_drop_off_step'] = funnel_df.iloc[i]['step']
return metrics
def generate_insights(self, funnel_df: pd.DataFrame,
segment_funnels: Dict[str, pd.DataFrame] = None) -> List[str]:
"""
Generate actionable insights from funnel analysis.
Args:
funnel_df: Main funnel DataFrame
segment_funnels: Optional segmented funnels for comparison
Returns:
List of insight strings
"""
insights = []
metrics = self.calculate_metrics(funnel_df)
# Overall conversion insights
if metrics['total_conversion_rate'] < 0.01:
insights.append("❗ Critical: Overall conversion rate is below 1%, requires immediate attention")
elif metrics['total_conversion_rate'] < 0.05:
insights.append("⚠️ Warning: Overall conversion rate is below 5%, optimization needed")
else:
insights.append(f"✓ Overall conversion rate is {metrics['total_conversion_rate']:.1%}")
# Drop-off insights
if metrics['biggest_drop_off_step']:
drop_off_pct = metrics['biggest_drop_off_rate'] * 100
insights.append(f"🎯 Biggest drop-off: {metrics['biggest_drop_off_step']} ({drop_off_pct:.1f}% loss)")
# Step-by-step insights
for i, row in funnel_df.iterrows():
if i > 0: # Skip first step
conv_rate = row['conversion_rate']
if conv_rate < 0.3:
insights.append(f"📉 {row['step']} has very low conversion ({conv_rate:.1%})")
elif conv_rate < 0.6:
insights.append(f"📊 {row['step']} has moderate conversion ({conv_rate:.1%})")
# Segment comparison insights
if segment_funnels:
best_segment = None
worst_segment = None
best_rate = 0
worst_rate = 1
for segment, seg_funnel in segment_funnels.items():
seg_metrics = self.calculate_metrics(seg_funnel)
if seg_metrics.get('total_conversion_rate', 0) > best_rate:
best_rate = seg_metrics['total_conversion_rate']
best_segment = segment
if seg_metrics.get('total_conversion_rate', 1) < worst_rate:
worst_rate = seg_metrics['total_conversion_rate']
worst_segment = segment
if best_segment and worst_segment:
insights.append(f"🏆 Best performing segment: {best_segment} ({best_rate:.1%})")
insights.append(f"🔻 Worst performing segment: {worst_segment} ({worst_rate:.1%})")
return insights
def export_report(self, funnel_df: pd.DataFrame,
segment_funnels: Dict[str, pd.DataFrame] = None,
filename: str = 'funnel_analysis_report.html') -> str:
"""
Export comprehensive funnel analysis report.
Args:
funnel_df: Main funnel DataFrame
segment_funnels: Optional segmented funnels
filename: Output filename
Returns:
Path to generated report file
"""
# Generate insights
insights = self.generate_insights(funnel_df, segment_funnels)
metrics = self.calculate_metrics(funnel_df)
# Create HTML report
html_content = f"""
<!DOCTYPE html>
<html>
<head>
<title>Funnel Analysis Report</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 40px; }}
.header {{ background-color: #f0f0f0; padding: 20px; border-radius: 5px; }}
.metrics {{ margin: 20px 0; }}
.insights {{ background-color: #f9f9f9; padding: 20px; border-radius: 5px; }}
table {{ border-collapse: collapse; width: 100%; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #f2f2f2; }}
</style>
</head>
<body>
<div class="header">
<h1>Funnel Analysis Report</h1>
<p>Generated on {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
</div>
<div class="metrics">
<h2>Key Metrics</h2>
<ul>
<li><strong>Total Conversion Rate:</strong> {metrics.get('total_conversion_rate', 0):.1%}</li>
<li><strong>Total Drop-off Rate:</strong> {metrics.get('total_drop_off_rate', 0):.1%}</li>
<li><strong>Biggest Drop-off:</strong> {metrics.get('biggest_drop_off_step', 'N/A')}</li>
</ul>
</div>
<div class="insights">
<h2>Key Insights</h2>
<ul>
{''.join([f'<li>{insight}</li>' for insight in insights])}
</ul>
</div>
<div>
<h2>Funnel Details</h2>
<table>
<tr>
<th>Step</th>
<th>Users</th>
<th>Conversion Rate</th>
<th>Drop-off Rate</th>
</tr>
"""
# Add funnel table rows
for i, row in funnel_df.iterrows():
if i == 0:
drop_off_rate = 0
else:
prev_users = funnel_df.iloc[i-1]['users']
drop_off_rate = 1 - (row['users'] / prev_users) if prev_users > 0 else 0
html_content += f"""
<tr>
<td>{row['step']}</td>
<td>{row['users']:,}</td>
<td>{row['conversion_rate']:.1%}</td>
<td>{drop_off_rate:.1%}</td>
</tr>
"""
html_content += """
</table>
</div>
</body>
</html>
"""
# Write to file
with open(filename, 'w', encoding='utf-8') as f:
f.write(html_content)
print(f"Report saved to {filename}")
return filename"""
Funnel Visualization Functions
This module provides visualization utilities for funnel analysis,
including interactive funnel charts, comparison charts, and detailed metrics.
"""
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np
from typing import Dict, List, Optional
class FunnelVisualizer:
"""
Class for creating funnel visualizations.
Provides methods for creating various types of funnel charts
and comparison visualizations.
"""
def __init__(self):
self.color_palette = px.colors.qualitative.Set3
def create_basic_funnel(self, funnel_df: pd.DataFrame,
title: str = "Conversion Funnel",
show_values: bool = True) -> go.Figure:
"""
Create a basic funnel chart.
Args:
funnel_df: DataFrame with funnel data
title: Chart title
show_values: Whether to show user counts
Returns:
Plotly figure object
"""
fig = go.Figure(go.Funnel(
y=funnel_df['step'],
x=funnel_df['users'],
textposition="inside",
textinfo="value+percent initial" if show_values else "percent initial",
marker=dict(color=self.color_palette[:len(funnel_df)])
))
fig.update_layout(
title={
'text': title,
'x': 0.5,
'xanchor': 'center',
'font': {'size': 20}
},
font=dict(size=14),
height=600
)
return fig
def create_segmented_funnel(self, segment_funnels: Dict[str, pd.DataFrame],
title: str = "Segmented Funnel Comparison") -> go.Figure:
"""
Create a side-by-side comparison of segmented funnels.
Args:
segment_funnels: Dictionary of segment names to funnel DataFrames
title: Chart title
Returns:
Plotly figure object
"""
segments = list(segment_funnels.keys())
colors = self.color_palette[:len(segments)]
fig = go.Figure()
for i, (segment, funnel_df) in enumerate(segment_funnels.items()):
fig.add_trace(go.Funnel(
name=segment,
y=funnel_df['step'],
x=funnel_df['users'],
textinfo="percent initial",
marker=dict(color=colors[i]),
opacity=0.8
))
fig.update_layout(
title={
'text': title,
'x': 0.5,
'xanchor': 'center',
'font': {'size': 20}
},
font=dict(size=12),
height=700
)
return fig
def create_conversion_rate_chart(self, funnel_df: pd.DataFrame,
title: str = "Step-by-Step Conversion Rates") -> go.Figure:
"""
Create a bar chart showing conversion rates between steps.
Args:
funnel_df: DataFrame with funnel data
title: Chart title
Returns:
Plotly figure object
"""
# Calculate step-to-step conversion rates
conv_rates = []
step_labels = []
for i in range(len(funnel_df)):
if i == 0:
conv_rates.append(1.0)
step_labels.append(f"{funnel_df.iloc[i]['step']}\n(100%)")
else:
prev_users = funnel_df.iloc[i-1]['users']
curr_users = funnel_df.iloc[i]['users']
rate = curr_users / prev_users if prev_users > 0 else 0
conv_rates.append(rate)
step_labels.append(f"{funnel_df.iloc[i]['step']}\n({rate:.1%})")
fig = go.Figure(data=[
go.Bar(
x=step_labels,
y=conv_rates,
marker=dict(color=self.color_palette[2]),
text=[f"{rate:.1%}" for rate in conv_rates],
textposition='auto',
)
])
fig.update_layout(
title={
'text': title,
'x': 0.5,
'xanchor': 'center',
'font': {'size': 20}
},
xaxis_title="Funnel Step",
yaxis_title="Conversion Rate",
yaxis=dict(tickformat='.0%'),
height=500
)
# Add reference line at 100%
fig.add_hline(y=1.0, line_dash="dash", line_color="red", opacity=0.5)
return fig
def create_drop_off_analysis(self, funnel_df: pd.DataFrame,
title: str = "Drop-off Analysis") -> go.Figure:
"""
Create a chart showing user drop-off at each step.
Args:
funnel_df: DataFrame with funnel data
title: Chart title
Returns:
Plotly figure object
"""
# Calculate drop-offs
drop_offs = []
drop_off_rates = []
step_names = []
for i, row in funnel_df.iterrows():
if i == 0:
drop_offs.append(0)
drop_off_rates.append(0.0)
step_names.append(row['step'])
else:
prev_users = funnel_df.iloc[i-1]['users']
curr_users = row['users']
drop_off = prev_users - curr_users
drop_off_rate = drop_off / prev_users if prev_users > 0 else 0
drop_offs.append(drop_off)
drop_off_rates.append(drop_off_rate)
step_names.append(row['step'])
# Create subplot
fig = make_subplots(
rows=2, cols=1,
subplot_titles=("Number of Users Dropped Off", "Drop-off Rate"),
vertical_spacing=0.1
)
# Add bar chart for absolute drop-offs
fig.add_trace(
go.Bar(
x=step_names,
y=drop_offs,
marker=dict(color=self.color_palette[4]),
name="Users Lost"
),
row=1, col=1
)
# Add bar chart for drop-off rates
fig.add_trace(
go.Bar(
x=step_names,
y=drop_off_rates,
marker=dict(color=self.color_palette[5]),
name="Drop-off Rate",
text=[f"{rate:.1%}" for rate in drop_off_rates],
textposition='auto'
),
row=2, col=1
)
fig.update_layout(
title={
'text': title,
'x': 0.5,
'xanchor': 'center',
'font': {'size': 20}
},
height=700,
showlegend=False
)
fig.update_yaxes(tickformat='.0%', row=2, col=1)
return fig
def create_segment_comparison(self, segment_funnels: Dict[str, pd.DataFrame],
metric: str = "total_conversion_rate",
title: str = "Segment Performance Comparison") -> go.Figure:
"""
Create a comparison chart of segments by a specific metric.
Args:
segment_funnels: Dictionary of segment names to funnel DataFrames
metric: Metric to compare ('total_conversion_rate' or 'biggest_drop_off')
title: Chart title
Returns:
Plotly figure object
"""
segments = []
values = []
for segment, funnel_df in segment_funnels.items():
segments.append(segment)
if metric == "total_conversion_rate":
if len(funnel_df) > 1:
start_users = funnel_df.iloc[0]['users']
end_users = funnel_df.iloc[-1]['users']
value = end_users / start_users if start_users > 0 else 0
else:
value = 0
elif metric == "biggest_drop_off":
max_drop_off = 0
for i in range(1, len(funnel_df)):
prev_users = funnel_df.iloc[i-1]['users']
curr_users = funnel_df.iloc[i]['users']
drop_off = 1 - (curr_users / prev_users) if prev_users > 0 else 0
max_drop_off = max(max_drop_off, drop_off)
value = max_drop_off
else:
value = 0
values.append(value)
fig = go.Figure(data=[
go.Bar(
x=segments,
y=values,
marker=dict(color=self.color_palette[:len(segments)]),
text=[f"{val:.1%}" for val in values],
textposition='auto',
)
])
y_axis_title = "Total Conversion Rate" if metric == "total_conversion_rate" else "Biggest Drop-off Rate"
fig.update_layout(
title={
'text': title,
'x': 0.5,
'xanchor': 'center',
'font': {'size': 20}
},
xaxis_title="Segment",
yaxis_title=y_axis_title,
yaxis=dict(tickformat='.0%'),
height=500
)
return fig
def create_comprehensive_dashboard(self, funnel_df: pd.DataFrame,
segment_funnels: Dict[str, pd.DataFrame] = None,
title: str = "Funnel Analysis Dashboard") -> go.Figure:
"""
Create a comprehensive dashboard with multiple visualizations.
Args:
funnel_df: Main funnel DataFrame
segment_funnels: Optional segmented funnels
title: Dashboard title
Returns:
Plotly figure object
"""
# Create subplots
if segment_funnels and len(segment_funnels) > 0:
fig = make_subplots(
rows=2, cols=2,
subplot_titles=(
"Conversion Funnel",
"Step Conversion Rates",
"Drop-off Analysis",
"Segment Comparison"
),
specs=[
[{"type": "funnel"}, {"type": "bar"}],
[{"type": "bar"}, {"type": "bar"}]
],
vertical_spacing=0.1,
horizontal_spacing=0.1
)
else:
fig = make_subplots(
rows=2, cols=2,
subplot_titles=(
"Conversion Funnel",
"Step Conversion Rates",
"Drop-off Analysis",
"User Counts per Step"
),
specs=[
[{"type": "funnel"}, {"type": "bar"}],
[{"type": "bar"}, {"type": "bar"}]
],
vertical_spacing=0.1,
horizontal_spacing=0.1
)
# Add main funnel (top left)
fig.add_trace(
go.Funnel(
y=funnel_df['step'],
x=funnel_df['users'],
name="Funnel",
marker=dict(color=self.color_palette[0])
),
row=1, col=1
)
# Add conversion rates (top right)
conv_rates = [1.0] # First step is always 100%
for i in range(1, len(funnel_df)):
prev_users = funnel_df.iloc[i-1]['users']
curr_users = funnel_df.iloc[i]['users']
rate = curr_users / prev_users if prev_users > 0 else 0
conv_rates.append(rate)
fig.add_trace(
go.Bar(
x=funnel_df['step'],
y=conv_rates,
name="Conv. Rates",
marker=dict(color=self.color_palette[1]),
text=[f"{rate:.1%}" for rate in conv_rates],
textposition='auto'
),
row=1, col=2
)
# Add drop-off analysis (bottom left)
drop_offs = [0] # First step has no drop-off
for i in range(1, len(funnel_df)):
prev_users = funnel_df.iloc[i-1]['users']
curr_users = funnel_df.iloc[i]['users']
drop_off = prev_users - curr_users
drop_offs.append(drop_off)
fig.add_trace(
go.Bar(
x=funnel_df['step'],
y=drop_offs,
name="Drop-offs",
marker=dict(color=self.color_palette[2])
),
row=2, col=1
)
# Add segment comparison or user counts (bottom right)
if segment_funnels and len(segment_funnels) > 0:
segments = list(segment_funnels.keys())
conv_rates_by_segment = []
for segment in segments:
seg_funnel = segment_funnels[segment]
if len(seg_funnel) > 1:
start_users = seg_funnel.iloc[0]['users']
end_users = seg_funnel.iloc[-1]['users']
rate = end_users / start_users if start_users > 0 else 0
else:
rate = 0
conv_rates_by_segment.append(rate)
fig.add_trace(
go.Bar(
x=segments,
y=conv_rates_by_segment,
name="Segment Rates",
marker=dict(color=self.color_palette[3]),
text=[f"{rate:.1%}" for rate in conv_rates_by_segment],
textposition='auto'
),
row=2, col=2
)
else:
fig.add_trace(
go.Bar(
x=funnel_df['step'],
y=funnel_df['users'],
name="User Counts",
marker=dict(color=self.color_palette[3])
),
row=2, col=2
)
fig.update_layout(
title={
'text': title,
'x': 0.5,
'xanchor': 'center',
'font': {'size': 24}
},
height=800,
showlegend=False
)
# Update y-axis format for conversion rates
fig.update_yaxes(tickformat='.0%', row=1, col=2)
if segment_funnels and len(segment_funnels) > 0:
fig.update_yaxes(tickformat='.0%', row=2, col=2)
return fig
def save_figure(self, fig: go.Figure, filename: str, format: str = 'html') -> str:
"""
Save figure to file.
Args:
fig: Plotly figure object
filename: Output filename
format: Output format ('html', 'png', 'pdf', 'svg')
Returns:
Path to saved file
"""
if format.lower() == 'html':
fig.write_html(filename)
elif format.lower() == 'png':
fig.write_image(filename)
elif format.lower() == 'pdf':
fig.write_image(filename)
elif format.lower() == 'svg':
fig.write_image(filename)
else:
raise ValueError(f"Unsupported format: {format}")
print(f"Figure saved to {filename}")
return filename