← Back to list

Day 22 Part 1: Audience Segmentation — Who Actually Engages With Your Content?

Saturday starting new system. Audience segmentation: cluster followers into meaningful groups using ML (K-Means, DBSCAN, Hierarchical…

Manav Gandhi · 2026-05-29 06:11 · 0 claps · 5.5 min read
#building-in-public #bufferapi #bufferiq #python #machine-learning
Open on Medium ↗
Wiki topics: ML · Machine Learning EDU · Education & Learning CRM · Email & CRM

Day 22 Part 1: Audience Segmentation — Who Actually Engages With Your Content?

Saturday starting new system. Audience segmentation: cluster followers into meaningful groups using ML (K-Means, DBSCAN, Hierarchical, GMM), generate persona profiles per segment (“The Driven Innovator”, “The Casual Browser”), track segment evolution over time, recommend content per segment. Goal: silhouette score ≥0.65, 88%+ persona accuracy, 20%+ engagement improvement per segment, ❤00ms processing. Scope: 100 files planned. Building conservatively after Day 20–21 lessons. Today: data preprocessing pipeline + clustering foundation. Won’t finish today. Multi-day build. #BufferAPI

Day 22 Part 1: New system starting.

Coming off Buffer API launch week.

Now: Building audience intelligence.

The Problem This Solves

Current State

BufferIQ currently:

  • Analyzes content quality (Day 16)
  • Checks voice consistency (Day 17)
  • Finds content gaps (Day 18)
  • Optimizes hashtags (Day 19)
  • Runs A/B tests (Day 20)
  • Analyzes images/videos/links (Day 21)

Missing:

All of this treats audience as one group.

Reality: Your audience = multiple different groups.

Why It Matters

Example: LinkedIn audience

Segment A: Senior engineers

  • Want: Technical deep-dives
  • Peak hours: 8–10 AM weekdays
  • Prefer: Long-form with code
  • Tone: Professional, precise

Segment B: Founders and entrepreneurs

  • Want: High-level strategy
  • Peak hours: 7 AM and 9 PM
  • Prefer: Short punchy insights
  • Tone: Energetic, forward-looking

Segment C: Junior developers

  • Want: Learning resources, tutorials
  • Peak hours: Lunch + evenings
  • Prefer: Step-by-step with examples
  • Tone: Approachable, encouraging

Same post can’t serve all three optimally.

Segmentation = personalization at scale.

What This System Does

Clusters audience → Generates personas → Recommends per segment

result = await service.segment_audience(
    audience_data=followers,
    platform="linkedin"
)
# Returns:
{
    "n_segments": 4,
    "personas": [
        {
            "name": "The Driven Innovator",
            "size": 847,
            "size_percentage": 34.2,
            "peak_hours": [8, 9, 10],
            "primary_topics": ["AI", "engineering", "leadership"],
            "recommended_tone": "professional",
            "predicted_engagement_lift": 23.4
        },
        ...
    ]
}

Each segment gets tailored recommendations.

Scope: 100 Files Planned

What I’m Building

7 subsystems:

  1. Data Preprocessing Pipeline (6 files)
  • Feature extraction from follower data
  • Normalization and scaling
  • Temporal feature engineering
  • Missing value handling
  1. Clustering Engine (8 files)
  • K-Means clustering
  • DBSCAN (density-based)
  • Hierarchical (Ward linkage)
  • Gaussian Mixture Models
  • Optimal cluster detection
  1. Persona Generator (7 files)
  • Demographic inference
  • Behavioral profiling
  • Interest mapping
  • Persona naming
  1. Segment Tracker (5 files)
  • Evolution over time
  • Member migration tracking
  • Drift detection
  • Health scoring
  1. Recommendation Engine (6 files)
  • Content recommendations per segment
  • Timing recommendations
  • Style recommendations
  • Hashtag recommendations
  1. Engagement Predictor (5 files)
  • Segment-specific models
  • Cross-segment analysis
  • Prediction calibration
  1. Intelligence Service (3 files)
  • Unified orchestrator
  • API endpoints

Plus: Tests (36), Domain models (4), API (8), Config (3), Scripts (5), Docs (5)

Total: 100 files

Honest Expectation

Day 20 lesson: Planned 105 files, delivered 51.

Day 21 lesson: Planned 95 files, delivered 89.

Day 22 approach:

Not rushing to hit 100 files.

Building core first. Quality maintained.

Phase 1 (today): Preprocessing + clustering foundation Phase 2 (tomorrow): Personas + tracking Phase 3 (Mon-Tue): Recommendations + prediction + integration

Won’t finish today. That’s fine.

What I’m Building Today

Part 1 Focus: Data Foundation

Goal: By end of day, clustering working on simulated data.

Building:

1. Core Types and Exceptions

SUPPORTED_PLATFORMS = ["linkedin", "twitter", "bluesky"]
@dataclass
class AudienceDataPoint:
    """Single audience member."""
    user_id: str
    platform: str
    follower_count: int
    avg_engagement_rate: float
    interaction_types: Dict[str, int]
    active_hours: List[int]
    topics_engaged: List[str]
    content_types_engaged: List[str]
    account_age_days: int
    # ...

2. Data Preprocessor

class AudienceDataPreprocessor:
    """Preprocess raw audience data into ML features."""

    def process(
        self,
        audience_data: List[AudienceDataPoint],
        platform: str
    ) -> List[ProcessedAudienceFeatures]:
        """
        Extract and normalize features.

        Features extracted:
        - follower_count_log (log scale)
        - following_ratio
        - post_frequency
        - avg_engagement_rate
        - like/comment/share/click ratios
        - active_hour_spread
        - peak_activity_hour
        - content type preferences
        - account_age_normalized
        - topic_diversity
        - platform-specific features
        """

Starting with 20+ features per audience member.

3. Clustering Optimizer

class ClusteringOptimizer:
    """Find optimal number of clusters."""

    def find_optimal(
        self,
        feature_matrix: np.ndarray,
        platform: str
    ) -> OptimalClusterConfig:
        """
        Tests k=2 to k=10.

        Metrics used:
        - Silhouette score (40% weight)
        - Calinski-Harabasz index (30% weight)
        - Davies-Bouldin index (30% weight)

        Returns best k with algorithm recommendation.
        """

4. K-Means Clusterer

class KMeansClusterer:
    """K-Means with stability testing."""

    def fit(
        self,
        feature_matrix: np.ndarray,
        n_clusters: int,
        platform: str
    ) -> ClusteringResult:
        """
        Runs 5 times with different seeds.
        Reports stability via adjusted rand score.
        Target: stability ≥ 0.80
        """

Testing today:

# Simulate 500 LinkedIn followers
audience = generate_test_audience(n=500, platform="linkedin")
# Preprocess
features = preprocessor.process(audience, "linkedin")
matrix = np.array([f.feature_vector for f in features])
# Find optimal k
optimal = optimizer.find_optimal(matrix, "linkedin")
print(f"Optimal clusters: {optimal.n_clusters}")
# Expected: 3-5 clusters
# Cluster
result = kmeans.fit(matrix, optimal.n_clusters, "linkedin")
print(f"Silhouette score: {result.silhouette_score}")
# Target: ≥ 0.65

If this works today = good foundation.

Integration Points

With Existing Systems

Every recommendation will use:

Day 16 content intelligence → What content quality per segment? Day 17 voice profiling → What tone per segment? Day 18 gap analysis → What topics missing per segment? Day 19 hashtag optimizer → What hashtags per segment? Day 20 A/B testing → Test segment-specific variants Day 21 multi-modal → Visual preferences per segment

Segmentation = personalization layer on top of everything.

Technical Decisions Made

Why 4 Clustering Algorithms?

K-Means: Fast, interpretable, works well for spherical clusters

DBSCAN: Handles noise, finds irregular cluster shapes

Hierarchical: Good for understanding cluster relationships, dendrogram

GMM: Probabilistic, soft assignments, handles overlapping segments

Will pick best for each platform:

LinkedIn: K-Means (tends to have cleaner segments) Twitter: DBSCAN (more noise in engagement patterns) Bluesky: GMM (smaller, overlapping communities)

Why Silhouette ≥ 0.65?

Silhouette score range: -1 to 1

  • <0.25: Poor clustering
  • 0.25–0.50: Reasonable
  • 0.50–0.70: Good
  • 0.70: Excellent

Target 0.65 = good clustering.

Not perfect. But meaningful segments.

Persona Naming

LinkedIn archetypes:

  • “The Driven Innovator”
  • “The Strategic Professional”
  • “The Engaged Networker”
  • “The Curious Analyst”

Twitter archetypes:

  • “The Active Commentator”
  • “The Content Curator”
  • “The Trend Explorer”

Bluesky archetypes:

  • “The Community Pioneer”
  • “The Thoughtful Builder”
  • “The Open Collaborator”

Names make segments actionable.

Not “Cluster 0.” But “The Driven Innovator.”

Performance Targets

Segmentation pipeline (full):

  • Target: ❤00ms P95
  • 100 members: <200ms
  • 10 personas: <500ms total

Why aggressive targets?

Real-time feedback needs speed.

User shouldn’t wait 2 seconds for segment analysis.

Will benchmark as I build.

Realistic Timeline

Today (Saturday):

  • Core types + exceptions: 30 min
  • Data preprocessor: 2h
  • Clustering optimizer: 1.5h
  • K-Means clusterer: 1h
  • DBSCAN clusterer: 1h
  • Tests: 1.5h
  • Integration test: 30 min
  • Total: ~8h
  • Target: 25% complete

Sunday:

  • Remaining clustering (GMM, hierarchical): 2h
  • Persona generator (all 7 files): 4h
  • Tests: 2h
  • Target: 55% complete

Monday:

  • Segment tracker: 2h
  • Recommendation engine: 3h
  • Tests: 1.5h
  • Target: 80% complete

Tuesday:

  • Engagement predictor: 2h
  • Intelligence service: 2h
  • API endpoints: 1.5h
  • Tests + polish: 1.5h
  • Target: 100% complete

Total estimate: ~30 hours across 4 days

Realistic with ×1.3 buffer: 39 hours

Personal Note

Post Buffer API launch week:

Energy different.

Launch week = external excitement.

This week = internal building.

Back to fundamentals.

Data. Algorithms. Tests.

Audience segmentation feels meaningful.

Not just a technical feature.

A genuine product capability.

“Who is my audience?” = question every creator asks.

BufferIQ will answer it with data.

Not guessing. Clustering.

Not generic personas. ML-derived segments.

That’s worth building carefully.

Starting now.

Day 22 Part 1 STARTING. Audience segmentation system: clusters followers using ML (K-Means DBSCAN Hierarchical GMM), generates personas per segment (The Driven Innovator The Strategic Professional etc), tracks evolution over time, recommends content timing style hashtags per segment. Why it matters: audience ≠ one group, same post can’t serve senior engineers + founders + junior devs optimally, segmentation = personalization at scale. Scope 100 files planned (preprocessing 6, clustering 8, personas 7, tracking 5, recommendations 6, prediction 5, intelligence 3, tests 36, API 8, etc). Honest expectation: won’t finish today, multi-day build, Phase 1 today preprocessing+clustering 25%, Phase 2 tomorrow personas+tracking 55%, Phase 3 Mon recommendations+prediction 80%, Phase 4 Tue service+API 100%. Today building: core types, data preprocessor (20+ features follower_count_log following_ratio engagement_rates active_hours topic_diversity), clustering optimizer (tests k=2 to k=10 silhouette 40% calinski 30% davies 30%), K-Means (stability testing 5 seeds adjusted_rand_score target ≥0.80), DBSCAN, target silhouette ≥0.65. Technical decisions: 4 algorithms different strengths, LinkedIn=K-Means Twitter=DBSCAN Bluesky=GMM, persona names not “Cluster 0” but “The Driven Innovator”. Performance ❤00ms P95. Integration: uses Days 16–21 all systems, personalization layer on top. Timeline 30h estimate ×1.3 buffer = 39h 4 days. Building carefully segmentation = genuine product capability answers “who is my audience” with data not guessing. #BufferAPI

Buffer 20 weeks: https://join.buffer.com/manav-gandhi

📖 github.com/27manavgandhi/BufferIQ

Day 22 Part 1 starting. Audience segmentation begins. Won’t rush. Building right.

25 days to go.

#BufferIQ #BufferAPI #BuildInPublic #Day22 #AudienceSegmentation #MachineLearning


메타데이터
post_id
990122ae3f6b
slug
day-22-part-1-audience-segmentation-who-actually-engages-with-your-content-990122ae3f6b
url
https://medium.com/@27manavgandhi/day-22-part-1-audience-segmentation-who-actually-engages-with-your-content-990122ae3f6b
canonical_url
https://medium.com/@27manavgandhi/day-22-part-1-audience-segmentation-who-actually-engages-with-your-content-990122ae3f6b
author_url
https://medium.com/@27manavgandhi
status
ok
fetched_at
2026-06-09 15:37:30