PO

posthog-migration-deep-dive

Migrate your analytics platform to PostHog using proven dual-write and event mapping strategies.

Install

mkdir -p .claude/skills/posthog-migration-deep-dive && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/2389" && unzip -o skill.zip -d .claude/skills/posthog-migration-deep-dive && rm skill.zip

Installs to .claude/skills/posthog-migration-deep-dive

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Migrate to PostHog from Google Analytics, Mixpanel, Amplitude, or Segment.
74 charsno explicit “when” trigger
Intermediate

Key capabilities

  • →Map old event names to PostHog event taxonomy
  • →Implement a dual-write adapter for analytics events
  • →Import historical data into PostHog
  • →Shift traffic gradually using feature flags
  • →Validate migration by comparing event counts

How it works

The skill maps event names and properties from a source platform to PostHog, then uses a dual-write adapter to send events to both platforms during a gradual traffic shift controlled by feature flags.

Inputs & outputs

You give it
Analytics events from Google Analytics, Mixpanel, Amplitude, or Segment
You get back
Event name and property mapping, dual-write adapter, historical data import script, feature flag cutover plan, and validation queries

When to use posthog-migration-deep-dive

  • →Migrating from Google Analytics 4 to PostHog
  • →Implementing a dual-write event pipeline
  • →Re-platforming Segment event destinations to PostHog
  • →Mapping legacy event schemas to PostHog

About this skill

PostHog Migration Deep Dive

Overview

Migrate from Google Analytics, Mixpanel, Amplitude, or Segment to PostHog using a dual-write strategy (send events to both old and new platforms) followed by gradual traffic shifting. PostHog's capture API accepts events in a format similar to Segment's track/identify calls, making migration straightforward.

Prerequisites

  • A paid product analytics plan and a dedicated target project are confirmed for historical imports.
  • The event taxonomy, distinct-ID map, timestamp policy, and rollback owner are approved.
  • A representative sample can be validated before full ingestion.

Authentication

  • Use the target project's public project token only for event capture. It is an ingestion identifier, not a secret or a credential for private APIs.
  • Use a least-privilege personal API key or OAuth token for private project APIs, keep it in a secret manager, and never place it in browser code, logs, examples, or committed files.
  • If server-side local feature-flag evaluation is required, use a feature flags secure API key through the SDK's personalApiKey option; do not reuse a broadly scoped personal API key.
  • Select the matching US or EU host for the target project before any sample or bulk write.

Migration Types

SourcePrimary discovery riskEvidence required before import
Google Analytics (GA4)Event and identity models differApproved taxonomy and identity mapping
MixpanelSimilar names can hide property or identity driftSample export reconciliation
AmplitudeCohort and user-property semantics can differProperty and timestamp comparison
SegmentDestination behavior can differ from direct SDK captureDual-write sample and delivery logs
Custom analyticsSource semantics are implementation-specificSource contract, resumable export, and representative sample

Instructions

Tool discipline

Use Read to inspect the relevant configuration and implementation before proposing changes. Use Write only for a new, explicitly requested artifact inside the target project. Use Edit for minimal changes to existing project files after the evidence pass.

Step 1: Event Name Mapping

Create a reviewed mapping table with source event, target event, source property, target property, source identity, target distinct ID, timestamp conversion, consent class, and owner. Reject unknown identities, empty event names, invalid timestamps, and unreviewed PII instead of silently coercing them.

Step 2: Dual-Write Adapter

Wrap the existing analytics boundary once, apply the frozen mapping before either destination, and attach a migration-run identifier. Track delivery results separately for the legacy and PostHog paths. The application path must remain successful when either analytics destination fails, and the adapter must expose independent kill switches plus a bounded flush on shutdown.

Step 3: Historical Data Import

import { PostHog } from 'posthog-node';

const importer = new PostHog(process.env.POSTHOG_PROJECT_TOKEN!, {
  host: process.env.POSTHOG_PUBLIC_HOST!,
  historicalMigration: true,
});

Historical imports require a paid product analytics plan even though the import itself is free. Use the Python or Node SDK, or the public batch endpoint, only with events dated at least 48 hours before import. Export to durable storage first, checkpoint every batch, preserve ISO 8601 timestamps and stable distinct IDs, and stop on the first reconciliation breach.

Step 4: Batch Import via HTTP API

{
  "api_key": "project-token-from-secret-source",
  "historical_migration": true,
  "batch": [
    {
      "event": "mapped_event_name",
      "properties": {"distinct_id": "stable-user-id", "migration_run": "approved-run-id"},
      "timestamp": "approved-iso-8601-timestamp"
    }
  ]
}

POST this shape to the selected regional /batch/ endpoint. Keep each request below the documented body-size limit, record its checkpoint and response, and never paste a real project token into a generated file or transcript.

Step 5: Feature Flag Controlled Cutover

Use explicit legacy, dual-write, and posthog-only states with legacy as the fail-closed default. If PostHog evaluates the cutover flag server-side, pass the feature flags secure API key through the SDK's personalApiKey option. Advance only after the approved observation window passes identity, count, property, timestamp, and business-metric reconciliation; roll back on any breach.

Step 6: Validation

set -euo pipefail
# Compare event counts between old platform and PostHog
echo "=== PostHog Event Counts (last 7 days) ==="
curl "https://us.posthog.com/api/projects/$POSTHOG_PROJECT_ID/query/" \
  -H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "kind": "HogQLQuery",
      "query": "SELECT event, count() AS total FROM events WHERE timestamp > now() - interval 7 day AND properties.migration_source = '"'"'dual-write'"'"' GROUP BY event ORDER BY total DESC LIMIT 20"
    }
  }' | jq '.results[] | {event: .[0], count: .[1]}'

Error Handling

IssueCauseSolution
Event counts don't matchSampling, identity, or timing differencesStop and compare against the migration's approved reconciliation tolerance
Historical import slowSingle-threadedUse batch endpoint, increase flushAt
Identity mismatchDifferent user ID formatsNormalize IDs in event map
Duplicate eventsDual-write without dedupUse migration_source property to filter

Output

  • Event name and property mapping from source platform
  • Dual-write adapter for gradual migration
  • Historical data import script
  • Feature flag controlled cutover plan
  • Validation queries comparing event counts

Examples

For a Mixpanel migration, freeze the event and identity map, run a tiny historical sample with historical_migration enabled, compare counts and properties, then expand in bounded batches. Keep live dual-write and historical import evidence separate, and stop on identity or timestamp drift.

Resources

See official PostHog references for current authority and verification boundaries.

When not to use it

  • →When the event model is fundamentally different, like with Google Analytics (GA4)
  • →When historical import is slow due to single-threaded processing
  • →When identity mismatch occurs due to different user ID formats

Limitations

  • →Migration from Google Analytics (GA4) is of medium complexity and takes 2-4 weeks
  • →Historical import can be slow if single-threaded
  • →Event counts may not match exactly due to sampling or timing differences

How it compares

This skill provides a structured, step-by-step migration process with dual-writing and feature flag-based traffic shifting, unlike a manual cutover.

Compared to similar skills

posthog-migration-deep-dive side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
posthog-migration-deep-dive (this skill)12moCautionIntermediate
mcp-builder1365moReviewAdvanced
supabase-developer959moReviewIntermediate
architecture-patterns554moNo flagsAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

More by jeremylongshore

View all by jeremylongshore →

analyzing-logs

jeremylongshore

Analyze application logs to detect performance issues, identify error patterns, and improve stability by extracting key insights.

14123

ollama-setup

jeremylongshore

Configure auto-configure Ollama when user needs local LLM deployment, free AI alternatives, or wants to eliminate hosted API costs. Trigger phrases: "install ollama", "local AI", "free LLM", "self-hosted AI", "replace OpenAI", "no API costs". Use when appropriate context detected. Trigger with relevant phrases based on skill purpose.

1167

backtesting-trading-strategies

jeremylongshore

Backtest crypto and traditional trading strategies against historical data. Calculates performance metrics (Sharpe, Sortino, max drawdown), generates equity curves, and optimizes strategy parameters. Use when user wants to test a trading strategy, validate signals, or compare approaches. Trigger with phrases like "backtest strategy", "test trading strategy", "historical performance", "simulate trades", "optimize parameters", or "validate signals".

1071

generating-database-seed-data

jeremylongshore

Process this skill enables AI assistant to generate realistic test data and database seed scripts for development and testing environments. it uses faker libraries to create realistic data, maintains relational integrity, and allows configurable data volumes. u... Use when working with databases or data models. Trigger with phrases like 'database', 'query', or 'schema'.

1033

cursor-codebase-indexing

jeremylongshore

Execute set up and optimize Cursor codebase indexing. Triggers on "cursor index setup", "codebase indexing", "index codebase", "cursor semantic search". Use when working with cursor codebase indexing functionality. Trigger with phrases like "cursor codebase indexing", "cursor indexing", "cursor".

885

testing-mobile-apps

jeremylongshore

Execute mobile app testing on iOS and Android devices/simulators. Use when performing specialized testing. Trigger with phrases like "test mobile app", "run iOS tests", or "validate Android functionality".

810

You might also like

mcp-builder

anthropics

Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

136215

supabase-developer

daffy0208

Build full-stack applications with Supabase (PostgreSQL, Auth, Storage, Real-time, Edge Functions). Use when implementing authentication, database design with RLS, file storage, real-time features, or serverless functions.

95185

architecture-patterns

wshobson

Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use when architecting complex backend systems or refactoring existing applications for better maintainability.

55214

dependency-upgrade

wshobson

Manage major dependency version upgrades with compatibility analysis, staged rollout, and comprehensive testing. Use when upgrading framework versions, updating major dependencies, or managing breaking changes in libraries.

26240

turborepo

vercel

Turborepo monorepo build system guidance. Triggers on: turbo.json, task pipelines, dependsOn, caching, remote cache, the "turbo" CLI, --filter, --affected, CI optimization, environment variables, internal packages, monorepo structure/best practices, and boundaries. Use when user: configures tasks/workflows/pipelines, creates packages, sets up monorepo, shares code between apps, runs changed/affected packages, debugs cache, or has apps/packages directories.

61191

telegram-bot-builder

davila7

Expert in building Telegram bots that solve real problems - from simple automation to complex AI-powered bots. Covers bot architecture, the Telegram Bot API, user experience, monetization strategies, and scaling bots to thousands of users. Use when: telegram bot, bot api, telegram automation, chat bot telegram, tg bot.

106130

Search skills

Search the agent skills registry