The gist
In this lesson you'll set up an automated analytics system: PostHog collects the data, Claude analyzes it, and every Monday morning a report lands in your messenger (Telegram in this example): what's working, what isn't, and what to do next.
Key concepts
- PostHog: open-source analytics with session recordings, feature flags, an API and an MCP server for Claude
- Mixpanel: powerful funnels and cohort analysis, with AI features (see the site for what's included)
- Plausible: privacy-first analytics, ideal for getting started without extra complexity
- DAU/MAU, Retention, Funnel: the three metrics that actually tell you about a product's health
- Churn prediction: Claude analyzes behavior patterns and predicts who's going to leave
- Session replay + AI: Claude reads session recordings and finds user pain points without you watching every video
- A/B testing with feature flags: PostHog runs the experiments, Claude interprets the results
- An automated weekly report: a Python script + the Claude API + a messenger = analytics on autopilot
Theory
Why an entrepreneur needs product analytics in 2026
Most solo entrepreneurs work blind. They look at the number of sign-ups and think everything's fine. But the real questions are different: how many of the people who signed up came back a week later? At which onboarding step do half the users drop off? Which feature gets used every day, and which one does nobody touch?
Answering these questions used to require a data analyst. Now you can get a lot of it from a properly set up Claude, but still double-check the conclusions: the model can make mistakes.
PostHog: open-source analytics with a brain
PostHog is the Swiss Army knife of product analytics. It's open source: you can install it on your own server or use their cloud. Each product has a free monthly allowance (current limits for analytics events and session recordings are on the PostHog pricing page). PostHog also has a built-in AI assistant (PostHog AI) that answers questions about your data.
What PostHog can do:
- Event tracking (clicks, page transitions, user actions)
- Session recordings: literally video recordings of what a user did
- Feature flags: turn features on and off for different groups
- Funnels: where users drop out of a process
- Cohorts: groups of users by behavior
- Experiments (A/B tests)
- PostHog MCP: a direct integration with Claude Code
PostHog MCP for Claude Code lets Claude query data from your PostHog directly, write HogQL queries (their query language) and analyze the results with no copy-pasting. It's currently PostHog's remote MCP server (address https://mcp.posthog.com/mcp; the data region is determined when you sign in to your account). Connecting it to Claude Code:
claude mcp add --transport http posthog https://mcp.posthog.com/mcpHow you authenticate depends on the version: follow PostHog's instructions for Claude Code (PostHog MCP documentation). Older examples with the @posthog/mcp-server package and a key in the config may not work.
After that you can ask in Claude Code: "Show me the top 5 events from the last week," and Claude will pull the data itself.
Mixpanel: professional-grade funnels and cohorts
Mixpanel specializes in behavioral analytics. If PostHog is a general-purpose tool, Mixpanel is the specialist in the question "why do users do X."
Mixpanel's strengths:
- Funnels with breakdowns by segment (paying vs free, mobile vs web)
- Cohort retention: you see which weeks' users stick around better
- Impact report: how a feature launch affected key metrics
- Built-in AI features for asking questions about your data (see the Mixpanel site for what's included and what it's called)
- Flows: visualizing user paths through the interface
The Mixpanel API for automation:
import requests
def get_mixpanel_funnel(project_id, funnel_id, api_secret):
url = f"https://mixpanel.com/api/2.0/funnels"
params = {
"funnel_id": funnel_id,
"from_date": "2026-09-01", # example: put in your own dates
"to_date": "2026-09-30",
}
response = requests.get(
url,
params=params,
auth=(api_secret, "")
)
return response.json()Mixpanel has a free tier with an event limit; terms and limits change, so check the site. API calls require your project details and a service account key: see the API reference for the current way to authenticate.
Plausible: getting started without overload
At the very beginning, when the product has just launched and there's little data, Plausible Analytics is the ideal choice. Simple setup (one script), privacy-first: it works without cookies, so in a typical setup you don't need a cookie banner. It's a paid service (with a trial period); plans are on the site.
Plausible is good for traffic analytics (where people come from, what they read), but for product analytics inside an app, PostHog or Mixpanel is better.
Key metrics: what really matters
Most entrepreneurs track too many metrics and miss the ones that matter. Here's the minimum set:
DAU/MAU (Daily/Monthly Active Users) The DAU/MAU percentage shows how "sticky" a product is. What's normal depends heavily on the type of product: people use a messenger every day and an accounting service once a month. Compare yourself to yourself over time and to similar products. If the percentage is close to zero, people aren't coming back, and that's a problem.
Cohort retention The classic retention report: of the users who signed up in week X, how many came back after 1 week, 2 weeks, 4 weeks. The main thing to watch is whether the curve flattens out: if some users stick around steadily, that's a good sign.
Funnel conversion What % of users go all the way from sign-up to active use. Onboarding usually loses a noticeable share of people. Finding where is the funnel's job.
Feature adoption Which features get used regularly, and which ones nobody touches after the first time.
Churn prediction with Claude
This is one of the most valuable things Claude can do with your data. Instead of reacting after a user has already left, predict who will leave next week and step in.
import anthropic
import json
def predict_churn(users_activity_data: list[dict]) -> dict:
"""
users_activity_data is a list of dicts with each user's activity:
[{"user_id": "u123", "last_login_days_ago": 8, "sessions_last_30d": 2,
"feature_usage": {"core": 5, "advanced": 0}, "plan": "free"}]
"""
client = anthropic.Anthropic()
prompt = f"""
You are a product analyst. Here is activity data for {len(users_activity_data)} users over the last 30 days:
{json.dumps(users_activity_data, ensure_ascii=False, indent=2)}
Analyze the patterns and:
1. Single out HIGH RISK users (likely to leave in the next 2 weeks)
2. Explain the signals you used to determine the risk
3. Suggest a specific action for each risk group (email, call, in-app notification)
Reply in JSON format:
{{
"high_risk": [list of user_id],
"medium_risk": [list of user_id],
"risk_signals": "explanation",
"actions": {{"high_risk": "action", "medium_risk": "action"}}
}}
"""
message = client.messages.create(
model="claude-sonnet-5-5", # current models: the "What's current" page
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
)
return json.loads("".join(b.text for b in message.content if b.type == "text"))A/B testing: feature flags + Claude as the interpreter
PostHog feature flags let you show different versions of the interface to different users. Claude helps you interpret the results without any knowledge of statistics.
The scenario: you're testing two versions of a checkout button. PostHog shows: Version A has a 4.2% conversion rate, Version B has 5.1%. Is it statistically significant? How long do you need to wait? Claude answers these questions.
def interpret_ab_test(test_data: dict) -> str:
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=512,
messages=[{
"role": "user",
"content": f"""
Analyze the results of an A/B test:
{json.dumps(test_data, ensure_ascii=False)}
Answer:
1. Which version won, and how confidently?
2. Is the result statistically significant (sample of {test_data.get('total_users', 'N/A')} users)?
3. Recommend: roll out the winner or wait for more data?
Answer in English, briefly, in 3-4 sentences.
"""
}]
)
return "".join(b.text for b in message.content if b.type == "text")Session replay + Claude: finding pain points without watching videos
PostHog records user sessions. At 1,000 users a day, that's 1,000 videos. Nobody's going to watch them. But Claude can read session metadata and surface patterns.
Session metadata includes: clicks, rage clicks (frantic clicking when something doesn't work), dead clicks (clicks on elements that aren't clickable), time on page, and the elements the user interacted with.
def analyze_session_patterns(sessions_metadata: list[dict]) -> str:
rage_clicks = [s for s in sessions_metadata if s.get("rage_clicks", 0) > 2]
high_exit_pages = {}
for session in sessions_metadata:
exit_page = session.get("exit_page", "")
high_exit_pages[exit_page] = high_exit_pages.get(exit_page, 0) + 1
analysis_data = {
"total_sessions": len(sessions_metadata),
"frustration_sessions": len(rage_clicks),
"top_exit_pages": sorted(
high_exit_pages.items(), key=lambda x: x[1], reverse=True
)[:5],
"avg_session_duration_minutes": sum(
s.get("duration_seconds", 0) for s in sessions_metadata
) / len(sessions_metadata) / 60
}
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=800,
messages=[{
"role": "user",
"content": f"""
User session data:
{json.dumps(analysis_data, ensure_ascii=False, indent=2)}
Find the main user pain points. What needs fixing first?
Answer: three specific problems with suggested fixes.
"""
}]
)
return "".join(b.text for b in message.content if b.type == "text")An automated weekly report
This is the main tool you'll set up in the practice section. A Python script runs every Monday, pulls last week's data from PostHog (with HogQL queries), hands it to Claude, gets back a human-readable report and sends it to your messenger. The example uses Telegram; if your team lives in Slack or email, ask Claude Code to swap the send_to_telegram function for that channel.
import os
import json
import anthropic
import requests
from datetime import datetime, timedelta
from dotenv import load_dotenv
load_dotenv()
# Keys come from .env, they're not written into the code
POSTHOG_PERSONAL_API_KEY = os.getenv("POSTHOG_PERSONAL_API_KEY") # personal key (phx_...) for reading data
POSTHOG_PROJECT_ID = os.getenv("POSTHOG_PROJECT_ID")
POSTHOG_HOST = os.getenv("POSTHOG_HOST", "https://us.posthog.com") # for Europe: https://eu.posthog.com
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID")
ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY")
def run_hogql(query: str) -> list:
"""Runs a HogQL query (PostHog's query language) through the API."""
response = requests.post(
f"{POSTHOG_HOST}/api/projects/{POSTHOG_PROJECT_ID}/query/",
headers={"Authorization": f"Bearer {POSTHOG_PERSONAL_API_KEY}"},
json={"query": {"kind": "HogQLQuery", "query": query}, "name": "weekly report"},
)
return response.json().get("results", []) if response.ok else []
def fetch_posthog_insights() -> dict:
"""Pull the key metrics for last week"""
end_date = datetime.now()
start_date = end_date - timedelta(days=7)
# Pageviews by day
pageviews_by_day = run_hogql(
"select toDate(timestamp) as day, count() from events "
"where event = '$pageview' and timestamp >= now() - interval 7 day "
"group by day order by day"
)
# Active users for the week
active_users = run_hogql(
"select count(distinct person_id) from events "
"where timestamp >= now() - interval 7 day"
)
# New sign-ups
signups = run_hogql(
"select count() from events "
"where event = 'signed_up' and timestamp >= now() - interval 7 day"
)
return {
"period": f"{start_date.strftime('%m/%d')} to {end_date.strftime('%m/%d/%Y')}",
"pageviews_by_day": pageviews_by_day,
"active_users": active_users,
"signups": signups,
}
def generate_weekly_report(insights: dict) -> str:
"""Claude writes a human-readable report"""
client = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY)
message = client.messages.create(
model="claude-sonnet-5-5", # current models: the "What's current" page
max_tokens=1500,
messages=[{
"role": "user",
"content": f"""
You are a product analyst. Here is the data for the week {insights['period']}:
{json.dumps(insights, ensure_ascii=False, indent=2, default=str)}
Write a weekly report for a startup founder. Structure:
📊 WEEK {insights['period']}
🟢 What's going well (2-3 points)
🔴 What needs attention (1-2 points)
🎯 This week's priority (1 specific action)
Tone: friendly, specific, no fluff. Write in English.
If there isn't much data, say so, don't invent reasons.
"""
}]
)
return "".join(b.text for b in message.content if b.type == "text")
def send_to_telegram(text: str):
"""Send the report to Telegram"""
requests.post(
f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage",
json={
"chat_id": TELEGRAM_CHAT_ID,
"text": text,
}
)
def run_weekly_report():
print("Collecting data from PostHog...")
insights = fetch_posthog_insights()
print("Claude is analyzing...")
report = generate_weekly_report(insights)
print("Sending to Telegram...")
send_to_telegram(report)
print("Done!")
if __name__ == "__main__":
run_weekly_report()This script runs via cron every Monday at 9:00:
0 9 * * 1 cd /path/to/project && python weekly_report.py
Practice
The task: set up an automated analytics system in 5 steps.
Step 1: Install PostHog (15 min)
- Go to posthog.com and create an account (there's a free tier)
- Create a project and get two keys. The
Project API Key(starts withphc_) is for sending events from your product. To read data with scripts you need a separate personal key (starts withphx_: in your account settings, under Personal API keys) and the project ID - Add tracking to your product (get the exact code and the
api_hostaddress for your region from the prompt in PostHog):
For a web app (HTML):
<script>
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){...}
posthog.init('phc_your_key', {api_host: 'https://us.i.posthog.com'}) // for Europe: https://eu.i.posthog.com
</script>For a Python backend:
pip install posthogfrom posthog import Posthog
posthog = Posthog('phc_your_key', host='https://us.i.posthog.com')
# Keyword arguments work across different versions of the library
posthog.capture(event='signed_up', distinct_id='user_123', properties={'plan': 'free', 'source': 'google'})- Check that events are coming in: go to PostHog → Activity → Live Events
Step 2: Set up the key funnels (10 min)
In PostHog → Funnels → New Funnel:
- Step 1:
signed_up(sign-up) - Step 2:
onboarding_completed(finished onboarding) - Step 3:
first_core_action(took the first key action) - Step 4:
payment_completed(paid)
Save the funnel. This is your main product health metric.
Step 3: Create the Python script for the weekly report (20 min)
mkdir analytics_bot
cd analytics_bot
pip install anthropic requests python-dotenvCreate a .env file (and add it to .gitignore):
POSTHOG_PERSONAL_API_KEY=phx_your_personal_key
POSTHOG_PROJECT_ID=your_project_id
POSTHOG_HOST=https://us.posthog.com
ANTHROPIC_API_KEY=sk-ant-your_key
TELEGRAM_BOT_TOKEN=your_token
TELEGRAM_CHAT_ID=your_chat_idCopy the weekly_report.py code from the theory section above. Run it:
python weekly_report.pyCheck that the report arrived in your messenger.
Step 4: Set up churn prediction (15 min)
Add a churn_detector.py script to the project:
from dotenv import load_dotenv
import os
import anthropic
import requests
import json
load_dotenv()
POSTHOG_HOST = os.getenv("POSTHOG_HOST", "https://us.posthog.com")
def get_at_risk_users():
"""Get users who haven't logged in for 7+ days (simplified: check the filter and fields against the PostHog docs)"""
headers = {"Authorization": f"Bearer {os.getenv('POSTHOG_PERSONAL_API_KEY')}"}
# Simplified query: users with low activity
response = requests.get(
f"{POSTHOG_HOST}/api/projects/{os.getenv('POSTHOG_PROJECT_ID')}/persons/",
headers=headers,
params={"properties": '[{"key":"$last_seen","value":"-7d","operator":"is_before_date"}]'}
)
if not response.ok:
return []
persons = response.json().get("results", [])
# Send only internal IDs and counters to the model, no names or emails
return [
{
"user_id": p.get("distinct_ids", ["unknown"])[0],
"last_seen": p.get("properties", {}).get("$last_seen"),
"total_sessions": p.get("properties", {}).get("$session_count", 0),
}
for p in persons[:50] # Take the first 50
]
def run_churn_check():
users = get_at_risk_users()
if not users:
print("No users at risk")
return
client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
message = client.messages.create(
model="claude-haiku-4-5", # Haiku is enough for this task (check that the model is still available in the API)
max_tokens=500,
messages=[{
"role": "user",
"content": f"""
Here are users who haven't logged in for a while ({len(users)} people):
{json.dumps(users[:10], ensure_ascii=False)}
What should we write to bring them back? One short email (3-4 sentences) for re-engagement.
"""
}]
)
print("Suggested re-engagement text:")
print("".join(b.text for b in message.content if b.type == "text"))
print(f"\nUsers at risk: {len(users)}")
if __name__ == "__main__":
run_churn_check()Step 5: Set up automatic runs (5 min)
# Open crontab
crontab -e
# Add these lines:
# Monday 9:00: weekly report
0 9 * * 1 cd /path/to/analytics_bot && python weekly_report.py
# Friday 17:00: churn check
0 17 * * 5 cd /path/to/analytics_bot && python churn_detector.py >> churn_log.txtChecking the result: within a week, your first automated report should show up in your messenger. If there isn't much data yet, that's normal: the system is working and building up history.
Tools and resources
| Tool | Price | What it's for |
|---|---|---|
| PostHog | A free monthly allowance for each product (current limits on the PostHog pricing page) | Core product analytics, session replay, flags |
| Mixpanel | There's a free tier, terms on the site | Funnels, cohorts, when you need deep behavioral analytics |
| Plausible | Paid, with a trial period, plans on the site | Privacy-first traffic analytics, early-stage projects |
| Amplitude | There's a free tier, terms on the site | An alternative to Mixpanel, strong retention analysis |
| PostHog MCP | Included in PostHog | Direct queries from Claude Code to PostHog |
| Claude Haiku | Pay per token | Routine analytics tasks |
| Claude Sonnet | Pay per token | Complex analysis, churn prediction |
Current prices and versions: What's current.
Useful links:
- PostHog Docs: official documentation
- PostHog MCP: connecting the MCP server
- Mixpanel API Reference: API documentation
- Amplitude SDK: if you go with Amplitude
Key takeaways
"Data without interpretation is noise. Claude turns noise into decisions."
"An automated weekly report in your messenger costs pennies in tokens and saves hours of manual summarizing. But double-check the numbers in it: the model retells the data, it doesn't replace an analyst."
"The best time to set up analytics is before launch. The second-best time is right now."
Next lesson
→ Niche and trend analysis: Exploding Topics, the Google Trends API and hunting for opportunities
The mark stays in this browser only and is never sent anywhere. My progress