Skip to content

PostHog GitHub Continuous AI

This guide introduces how to integrate PostHog and GitHub to build continuous product analytics and AI-driven decision-making systems.

Overview

By combining PostHog's product analytics capabilities with GitHub's code management, ByteBuddy can:

  • Automatically analyze user behavior data
  • Generate product improvement recommendations based on data
  • Create data-driven Issues and PRs
  • Monitor feature performance after release

Configuration

1. Install Required MCP Servers

bash
npm install -g posthog-mcp-server github-mcp-server

2. Configure ByteBuddy

json
{
  "mcpServers": {
    "posthog": {
      "command": "node",
      "args": ["posthog-mcp-server"],
      "env": {
        "POSTHOG_API_KEY": "your-posthog-api-key",
        "POSTHOG_HOST": "https://app.posthog.com"
      }
    },
    "github": {
      "command": "node",
      "args": ["github-mcp-server"],
      "env": {
        "GITHUB_TOKEN": "your-github-token"
      }
    }
  }
}

Use Cases

Scenario 1: Automated Product Insights

typescript
// Product insights automation
class ProductInsights {
  async generateWeeklyInsights() {
    // Get data from the past week
    const weeklyData = await mcp.call("posthog.getEvents", {
      events: ["$pageview", "$autocapture"],
      date_from: "-7d",
      date_to: "now",
      properties: [],
    });

    // Analyze key metrics
    const insights = await this.analyzeKeyMetrics(weeklyData);

    // Generate improvement recommendations
    const recommendations = await this.generateRecommendations(insights);

    // Create GitHub Issues
    for (const recommendation of recommendations) {
      await this.createInsightIssue(recommendation);
    }

    return insights;
  }

  private async analyzeKeyMetrics(data: any) {
    return {
      userEngagement: this.calculateEngagement(data),
      featureUsage: this.analyzeFeatureUsage(data),
      conversionRates: this.calculateConversionRates(data),
      dropOffPoints: this.identifyDropOffPoints(data),
      performance: this.analyzePerformance(data),
    };
  }

  private async generateRecommendations(insights: any) {
    const recommendations = [];

    // User engagement analysis
    if (insights.userEngagement.score < 0.7) {
      recommendations.push({
        title: "Improve User Engagement",
        description: `Current user engagement score is ${insights.userEngagement.score}, below target value`,
        type: "enhancement",
        priority: "high",
        suggestedActions: [
          "Optimize homepage loading speed",
          "Improve user onboarding flow",
          "Add personalized recommendations",
        ],
      });
    }

    // Feature usage analysis
    const lowUsageFeatures = insights.featureUsage.filter((f) => f.usage < 0.1);
    for (const feature of lowUsageFeatures) {
      recommendations.push({
        title: `Low Usage of Feature ${feature.name}`,
        description: `Feature ${feature.name} usage is only ${(feature.usage * 100).toFixed(2)}%`,
        type: "enhancement",
        priority: "medium",
        suggestedActions: [
          "Improve feature visibility",
          "Add feature usage guidance",
          "Collect user feedback",
        ],
      });
    }

    return recommendations;
  }

  private async createInsightIssue(recommendation: any) {
    const issueBody = this.generateIssueBody(recommendation);

    return await mcp.call("github.createIssue", {
      owner: "your-org",
      repo: "your-repo",
      title: recommendation.title,
      body: issueBody,
      labels: ["data-driven", recommendation.type, recommendation.priority],
      assignees: this.findAssignees(recommendation.type),
    });
  }
}

Scenario 2: A/B Test Analysis

typescript
// A/B test automated analysis
class ABTestAnalysis {
  async analyzeABTest(testId: string) {
    // Get test data
    const testData = await mcp.call("posthog.getExperimentResults", {
      experiment_id: testId,
      date_from: "-30d",
      date_to: "now",
    });

    // Statistical analysis
    const analysis = this.performStatisticalAnalysis(testData);

    // Generate report
    const report = await this.generateTestReport(testId, analysis);

    // If test has clear results, automatically create PR
    if (analysis.winner) {
      await this.createWinnerPR(testId, analysis.winner);
    }

    return report;
  }

  private performStatisticalAnalysis(testData: any) {
    // Calculate statistical significance
    const variants = testData.variants.map((variant) => ({
      name: variant.key,
      conversionRate: variant.conversion_rate,
      sampleSize: variant.participants,
      confidence: this.calculateConfidence(variant),
      uplift: this.calculateUplift(variant, testData.control),
    }));

    // Determine winner
    const winner = this.determineWinner(variants);

    return {
      variants,
      winner,
      statisticalSignificance: this.isStatisticallySignificant(testData),
      testDuration: this.calculateTestDuration(testData),
      recommendations: this.generateTestRecommendations(variants),
    };
  }

  private async createWinnerPR(testId: string, winner: any) {
    const prTitle = `Implement winning variant: ${winner.name} for test ${testId}`;
    const prBody = this.generatePRBody(testId, winner);

    return await mcp.call("github.createPullRequest", {
      owner: "your-org",
      repo: "your-repo",
      title: prTitle,
      body: prBody,
      head: `feature/test-${testId}-${winner.name}`,
      base: "main",
    });
  }
}

Scenario 3: User Feedback Integration

typescript
// User feedback automated processing
class UserFeedbackProcessor {
  async processFeedback() {
    // Get recent feedback
    const feedback = await mcp.call("posthog.getSurveyResponses", {
      survey_id: "user-satisfaction",
      date_from: "-7d",
    });

    // Analyze feedback trends
    const trends = await this.analyzeFeedbackTrends(feedback);

    // Create issues or improvement tasks
    for (const trend of trends) {
      if (trend.severity === "high") {
        await this.createFeedbackIssue(trend);
      }
    }

    return trends;
  }

  private async analyzeFeedbackTrends(feedback: any[]) {
    // Use sentiment analysis
    const sentimentAnalysis = await this.performSentimentAnalysis(feedback);

    // Identify common issues
    const commonIssues = this.identifyCommonIssues(feedback);

    // Trend analysis
    const trends = [];

    for (const issue of commonIssues) {
      if (issue.count > 5) {
        trends.push({
          issue: issue.description,
          count: issue.count,
          sentiment: sentimentAnalysis[issue.description],
          severity: this.calculateSeverity(
            issue.count,
            sentimentAnalysis[issue.description],
          ),
          affectedUsers: issue.users.length,
        });
      }
    }

    return trends;
  }

  private async createFeedbackIssue(trend: any) {
    const issueBody = `
## User Feedback Trend Analysis

**Issue Description**: ${trend.issue}

**Affected Users**: ${trend.affectedUsers}

**Feedback Count**: ${trend.count}

**Sentiment Analysis**: ${trend.sentiment.label} (Confidence: ${trend.sentiment.confidence})

**Severity**: ${trend.severity}

## Recommended Actions

1. Investigate specific user scenarios
2. Develop solutions
3. Track improvement effectiveness

## Related Data

- PostHog Dashboard: [View detailed data](https://app.posthog.com/insights)
- User feedback records: Exported to attachment
    `;
    return await mcp.call("github.createIssue", {
      owner: "your-org",
      repo: "your-repo",
      title: `User Feedback: ${trend.issue}`,
      body: issueBody,
      labels: ["user-feedback", trend.severity, "data-driven"],
    });
  }
}

Continuous Monitoring

1: Performance Monitoring

typescript
// Product performance monitoring
class PerformanceMonitor {
  async monitorProductHealth() {
    const healthChecks = [
      this.checkPageLoadTimes(),
      this.checkErrorRates(),
      this.checkUserSatisfaction(),
      this.checkFeaturePerformance(),
    ];

    const results = await Promise.allSettled(healthChecks);

    const healthReport = {
      overall: "healthy",
      metrics: {},
      alerts: [],
    };

    results.forEach((result, index) => {
      const metricName = [
        "pageLoad",
        "errorRate",
        "userSatisfaction",
        "featurePerformance",
      ][index];

      if (result.status === "fulfilled") {
        healthReport.metrics[metricName] = result.value;

        if (result.value.status !== "healthy") {
          healthReport.alerts.push({
            metric: metricName,
            severity: result.value.severity,
            message: result.value.message,
          });
        }
      }
    });

    // If there are alerts, create Issue
    if (healthReport.alerts.length > 0) {
      await this.createHealthAlert(healthReport);
    }

    return healthReport;
  }

  private async checkPageLoadTimes() {
    const performanceData = await mcp.call("posthog.getInsight", {
      insight_id: "page-load-times",
      date_from: "-24h",
    });

    const avgLoadTime = performanceData.result[0].value;

    return {
      status: avgLoadTime < 3000 ? "healthy" : "warning",
      value: avgLoadTime,
      threshold: 3000,
      message: `Average page load time: ${avgLoadTime}ms`,
    };
  }

  private async createHealthAlert(healthReport: any) {
    const alertBody = `
## Product Health Status Alert

**Overall Status**: ${healthReport.overall}

### Key Metrics

${Object.entries(healthReport.metrics)
  .map(
    ([key, value]: [string, any]) =>
      `- **${key}**: ${value.message} (${value.status})`,
  )
  .join("\n")}

### Alert Details

${healthReport.alerts
  .map(
    (alert) =>
      `- **${alert.metric}**: ${alert.message} (Severity: ${alert.severity})`,
  )
  .join("\n")}

### Recommended Actions

1. Immediately investigate high-severity issues
2. Develop improvement plans
3. Increase monitoring frequency

---
*This alert was automatically generated by ByteBuddy*
    `;
    return await mcp.call("github.createIssue", {
      owner: "your-org",
      repo: "your-repo",
      title: "Product Health Status Alert",
      body: alertBody,
      labels: ["health-alert", "automated", "monitoring"],
    });
  }
}

Automated Workflows

1: Daily Reports

typescript
// Automated daily reporting
class DailyReporter {
  async generateDailyReport() {
    const reportDate = new Date().toISOString().split("T")[0];

    // Collect data
    const data = {
      analytics: await this.getAnalyticsData(),
      github: await this.getGitHubActivity(),
      errors: await this.getErrorData(),
      performance: await this.getPerformanceData(),
    };

    // Generate report
    const report = await this.compileReport(data, reportDate);

    // Publish to GitHub
    await this.publishReport(report, reportDate);

    // Send notification
    await this.sendSummary(report);

    return report;
  }

  private async getAnalyticsData() {
    return await mcp.call("posthog.getInsight", {
      insight_id: "daily-overview",
      date_from: "-1d",
      date_to: "now",
    });
  }

  private async publishReport(report: any, date: string) {
    const reportPath = `reports/daily-${date}.md`;

    // Create or update report file
    await mcp.call("github.createOrUpdateFile", {
      owner: "your-org",
      repo: "your-repo",
      path: reportPath,
      message: `Daily report for ${date}`,
      content: report.content,
      branch: "main",
    });

    // Create Issue to discuss report
    await mcp.call("github.createIssue", {
      owner: "your-org",
      repo: "your-repo",
      title: `Daily Report - ${date}`,
      body: `## Daily Report Summary

${report.summary}

[View detailed report](https://github.com/your-org/your-repo/blob/main/${reportPath})

### Key Metrics

${report.keyMetrics
  .map((metric) => `- **${metric.name}**: ${metric.value} (${metric.trend})`)
  .join("\n")}
      `,
      labels: ["daily-report", "automated"],
    });
  }
}

Best Practices

1: Data Quality Assurance

typescript
// Data quality checking
class DataQualityChecker {
  async checkDataQuality() {
    const checks = [
      this.checkDataCompleteness(),
      this.checkDataAccuracy(),
      this.checkDataConsistency(),
      this.checkDataTimeliness(),
    ];

    const results = await Promise.allSettled(checks);

    const qualityReport = {
      overall: "good",
      issues: [],
      recommendations: [],
    };

    results.forEach((result, index) => {
      if (
        result.status === "rejected" ||
        (result.status === "fulfilled" && !result.value.passed)
      ) {
        qualityReport.issues.push({
          check: ["completeness", "accuracy", "consistency", "timeliness"][
            index
          ],
          issue: result.reason || result.value.issue,
        });
      }
    });

    return qualityReport;
  }
}

Through deep integration of PostHog and GitHub, ByteBuddy can build powerful data-driven decision-making systems, making product development more intelligent and efficient.