Claude-code-plugins posthog-core-workflow-a
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/posthog-pack/skills/posthog-core-workflow-a" ~/.claude/skills/jeremylongshore-claude-code-plugins-posthog-core-workflow-a && rm -rf "$T"
manifest:
plugins/saas-packs/posthog-pack/skills/posthog-core-workflow-a/SKILL.mdsource content
PostHog Core Workflow A — Product Analytics
Overview
Primary PostHog workflow covering event capture, user identification, group analytics, and person properties. This is the foundation for all PostHog analytics: capturing what users do, linking events to identified users, and grouping users by company/team for B2B analytics.
Prerequisites
- Completed
setupposthog-install-auth
(browser) and/orposthog-js
(server) installedposthog-node- Project API key (
) configuredphc_...
Instructions
Step 1: Define Event Taxonomy
// src/analytics/events.ts // Define all events as typed constants for consistency export const EVENTS = { // User lifecycle USER_SIGNED_UP: 'user_signed_up', USER_LOGGED_IN: 'user_logged_in', USER_ONBOARDING_COMPLETED: 'user_onboarding_completed', // Core product actions FEATURE_USED: 'feature_used', ITEM_CREATED: 'item_created', ITEM_UPDATED: 'item_updated', ITEM_DELETED: 'item_deleted', SEARCH_PERFORMED: 'search_performed', EXPORT_COMPLETED: 'export_completed', // Revenue events SUBSCRIPTION_STARTED: 'subscription_started', SUBSCRIPTION_UPGRADED: 'subscription_upgraded', SUBSCRIPTION_CANCELED: 'subscription_canceled', PAYMENT_COMPLETED: 'payment_completed', } as const; // Standard property schema for consistency across events interface BaseProperties { source?: 'web' | 'mobile' | 'api' | 'webhook'; plan_tier?: 'free' | 'pro' | 'enterprise'; duration_ms?: number; }
Step 2: Capture Events (Browser)
import posthog from 'posthog-js'; import { EVENTS } from './events'; // Custom event with properties posthog.capture(EVENTS.ITEM_CREATED, { item_type: 'document', source: 'web', plan_tier: 'pro', }); // Timed event (measure duration) const start = performance.now(); await doExpensiveOperation(); posthog.capture(EVENTS.EXPORT_COMPLETED, { format: 'csv', row_count: 1500, duration_ms: Math.round(performance.now() - start), }); // Pageview with custom properties (if capture_pageview: false) posthog.capture('$pageview', { page_title: document.title, referrer: document.referrer, });
Step 3: Identify Users and Set Properties
// After user logs in — links anonymous events to this user posthog.identify('user-456', { // $set properties (persist, overwrite on change) email: 'jane@acme.com', name: 'Jane Smith', plan: 'enterprise', signup_date: '2025-06-15', }); // Update properties later without re-identifying posthog.people.set({ last_active: new Date().toISOString(), total_items: 42, }); // Set properties only if not already set ($set_once) posthog.people.set_once({ first_seen: new Date().toISOString(), original_referrer: document.referrer, }); // Unset properties posthog.people.unset(['deprecated_field']); // Reset on logout (clears distinct_id, starts new anonymous session) posthog.reset();
Step 4: Group Analytics (B2B Company Tracking)
// Associate user with a company group posthog.group('company', 'company-789', { name: 'Acme Corp', industry: 'SaaS', plan: 'enterprise', employee_count: 150, arr: 250000, }); // Events now automatically include company context posthog.capture(EVENTS.FEATURE_USED, { feature_name: 'bulk-export', }); // This event is attributed to both user-456 AND company-789 // Multiple group types posthog.group('team', 'team-alpha', { name: 'Alpha Team' });
Step 5: Server-Side Event Capture (posthog-node)
import { PostHog } from 'posthog-node'; const posthog = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { host: 'https://us.i.posthog.com', }); // Server-side capture (e.g., in API route or webhook handler) function trackServerEvent(userId: string, event: string, properties?: Record<string, any>) { posthog.capture({ distinctId: userId, event, properties: { ...properties, source: 'api', }, }); } // Identify with server-side properties posthog.identify({ distinctId: 'user-456', properties: { subscription_status: 'active', mrr: 99, }, }); // Group identify from server posthog.groupIdentify({ groupType: 'company', groupKey: 'company-789', properties: { plan: 'enterprise', total_seats: 50, }, }); // CRITICAL: Flush in serverless/edge functions await posthog.flush();
Step 6: Create Annotations for Context
set -euo pipefail # Mark a deployment or product change in PostHog curl -X POST "https://app.posthog.com/api/projects/$POSTHOG_PROJECT_ID/annotations/" \ -H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "v2.5.0 deployed — new checkout flow", "date_marker": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'", "scope": "project" }'
Error Handling
| Error | Cause | Solution |
|---|---|---|
| Events not appearing | not called | Ensure init runs before any capture |
| Anonymous/identified split | Different across platforms | Use consistent user ID from your auth system |
| Group data missing | not called | Call before capture for group attribution |
| Server events lost | No in serverless | Always call before response |
| Properties not updating | Using for mutable data | Use for values that change |
Output
- Typed event taxonomy for consistent tracking
- Browser event capture with user identification
- B2B group analytics linking users to companies
- Server-side event capture with proper flushing
- Annotations marking deployments and product changes
Resources
Next Steps
For feature flags and experiments, see
posthog-core-workflow-b.