product-analytics
Event tracking architecture, funnels, cohorts, A/B testing, PostHog/Amplitude
What this skill does
# Product Analytics
## Overview
This skill covers designing and implementing product analytics systems that provide actionable insights into user behavior. It addresses event taxonomy design, analytics SDK integration with major platforms (PostHog, Amplitude, Mixpanel, Segment), funnel and cohort analysis, A/B testing and feature flags, user journey mapping, GDPR-compliant consent management, and custom metric definitions.
Use this skill when adding analytics to a new product, redesigning an event tracking system, setting up A/B testing infrastructure, implementing consent management, or building custom dashboards for product teams.
---
## Core Principles
1. **Design the taxonomy before writing code** - A well-designed event naming convention and property schema prevents the #1 analytics failure: inconsistent, unqueryable data. Agree on naming conventions first.
2. **Track actions, not pages** - Page views tell you where users went. Events with context tell you what users did and why. Focus on user actions: `project_created`, `file_uploaded`, `subscription_upgraded`.
3. **Identify before you track** - Every event needs a user identity. Anonymous events before signup should be linked to the authenticated identity once the user logs in (alias/merge).
4. **Consent is mandatory** - GDPR and CCPA require explicit user consent before tracking. Build consent management into the analytics layer, not as an afterthought.
5. **Less is more** - Tracking everything creates noise. Track the events that answer specific product questions. You can always add events later; removing noise from existing data is much harder.
---
## Key Patterns
### Pattern 1: Event Taxonomy Design
**When to use:** Before implementing any analytics tracking. This is the foundation everything else builds on.
**Implementation:**
```typescript
// Event taxonomy schema
// Convention: object_action (noun_verb in past tense)
// Core event types
type AnalyticsEvent =
// Authentication
| { event: "user_signed_up"; properties: { method: "email" | "google" | "github"; referralSource?: string } }
| { event: "user_logged_in"; properties: { method: "email" | "google" | "github" } }
| { event: "user_logged_out"; properties: Record<string, never> }
// Onboarding
| { event: "onboarding_started"; properties: { variant?: string } }
| { event: "onboarding_step_completed"; properties: { step: number; stepName: string } }
| { event: "onboarding_completed"; properties: { durationSeconds: number } }
| { event: "onboarding_skipped"; properties: { lastStep: number } }
// Core product actions
| { event: "project_created"; properties: { template?: string; source: "dashboard" | "onboarding" | "api" } }
| { event: "project_deleted"; properties: { projectAge: number; itemCount: number } }
| { event: "file_uploaded"; properties: { fileType: string; fileSizeBytes: number; source: "drag_drop" | "file_picker" | "api" } }
// Subscription
| { event: "subscription_started"; properties: { plan: string; billingCycle: "monthly" | "annual"; amount: number } }
| { event: "subscription_upgraded"; properties: { fromPlan: string; toPlan: string } }
| { event: "subscription_cancelled"; properties: { reason?: string; plan: string; tenureDays: number } }
// Feature engagement
| { event: "feature_used"; properties: { feature: string; context: string } }
| { event: "search_performed"; properties: { query: string; resultCount: number; source: string } }
| { event: "export_completed"; properties: { format: "csv" | "pdf" | "json"; itemCount: number } };
// Type-safe tracking function
function track<T extends AnalyticsEvent>(
event: T["event"],
properties: T["properties"]
): void {
// Implementation below
}
// Usage - fully typed, autocomplete works
track("project_created", {
template: "blank",
source: "dashboard",
});
```
**Why:** A typed event taxonomy prevents typos (`user_signedup` vs `user_signed_up`), ensures required properties are always present, and makes the tracking plan self-documenting. The `object_action` convention groups related events together in analytics dashboards.
---
### Pattern 2: Analytics Client with Consent Management
**When to use:** Every product that tracks user behavior, which is every product.
**Implementation:**
```typescript
// analytics.ts - Unified analytics client
import posthog from "posthog-js";
type ConsentStatus = "granted" | "denied" | "pending";
interface AnalyticsConfig {
posthogKey: string;
posthogHost?: string;
}
class Analytics {
private initialized = false;
private consent: ConsentStatus = "pending";
private queuedEvents: Array<{ event: string; properties: Record<string, unknown> }> = [];
init(config: AnalyticsConfig) {
posthog.init(config.posthogKey, {
api_host: config.posthogHost ?? "https://us.i.posthog.com",
persistence: "localStorage+cookie",
autocapture: false, // Explicit tracking only
capture_pageview: false, // Manual pageview tracking
capture_pageleave: true,
// Respect Do Not Track
respect_dnt: true,
// Cookie-less mode until consent
persistence: this.consent === "granted" ? "localStorage+cookie" : "memory",
});
this.initialized = true;
}
setConsent(status: ConsentStatus) {
this.consent = status;
if (status === "granted") {
posthog.opt_in_capturing();
// Flush queued events
for (const event of this.queuedEvents) {
this.trackInternal(event.event, event.properties);
}
this.queuedEvents = [];
} else if (status === "denied") {
posthog.opt_out_capturing();
this.queuedEvents = [];
}
}
identify(userId: string, traits?: Record<string, unknown>) {
if (this.consent !== "granted") return;
posthog.identify(userId, traits);
}
// Alias anonymous ID to authenticated ID (for signup flow)
alias(newId: string) {
if (this.consent !== "granted") return;
posthog.alias(newId);
}
track(event: string, properties?: Record<string, unknown>) {
if (this.consent === "denied") return;
const enrichedProperties = {
...properties,
timestamp: new Date().toISOString(),
url: typeof window !== "undefined" ? window.location.href : undefined,
referrer: typeof document !== "undefined" ? document.referrer : undefined,
};
if (this.consent === "pending") {
this.queuedEvents.push({ event, properties: enrichedProperties });
return;
}
this.trackInternal(event, enrichedProperties);
}
private trackInternal(event: string, properties: Record<string, unknown>) {
if (!this.initialized) return;
posthog.capture(event, properties);
}
page(name?: string, properties?: Record<string, unknown>) {
this.track("$pageview", { pageName: name, ...properties });
}
reset() {
posthog.reset();
}
}
export const analytics = new Analytics();
```
```tsx
// React consent banner component
function ConsentBanner() {
const [showBanner, setShowBanner] = useState(() => {
return localStorage.getItem("analytics_consent") === null;
});
const handleConsent = (granted: boolean) => {
const status = granted ? "granted" : "denied";
localStorage.setItem("analytics_consent", status);
analytics.setConsent(status);
setShowBanner(false);
};
if (!showBanner) return null;
return (
<div role="dialog" aria-label="Cookie consent" className="consent-banner">
<p>We use analytics to improve our product. No personal data is sold.</p>
<div className="consent-actions">
<button onClick={() => handleConsent(false)}>Decline</button>
<button onClick={() => handleConsent(true)}>Accept</button>
</div>
</div>
);
}
```
**Why:** Consent-first analytics is legally required (GDPR, CCPA) and builds user trust. The queue pattern ensures no events are lost if the user grants consent after performing actions. Explicit tracking (no autocapture) keeps data clean andRelated in Data & Analytics
clawarr-suite
IncludedComprehensive management for self-hosted media stacks (Sonarr, Radarr, Lidarr, Readarr, Prowlarr, Bazarr, Overseerr, Plex, Tautulli, SABnzbd, Recyclarr, Unpackerr, Notifiarr, Maintainerr, Kometa, FlareSolverr). Deep library exploration, analytics, dashboard generation, content management, request handling, subtitle management, indexer control, download monitoring, quality profile sync, library cleanup automation, notification routing, collection/overlay management, and media tracker integration (Trakt, Letterboxd, Simkl).
querying-soql
IncludedSOQL query generation, optimization, and analysis with 100-point scoring. Use this skill when the user needs SOQL/SOSL authoring or optimization: natural-language-to-query generation, relationship queries, aggregates, query-plan analysis, and performance or safety improvements for Salesforce queries. TRIGGER when: user writes, optimizes, or debugs SOQL/SOSL queries, touches .soql files, or asks about relationship queries, aggregates, or query performance. DO NOT TRIGGER when: bulk data operations (use handling-sf-data), Apex DML logic (use generating-apex), or report/dashboard queries.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
habit-flow
IncludedAI-powered atomic habit tracker with natural language logging, streak tracking, smart reminders, and coaching. Use for creating habits, logging completions naturally ("I meditated today"), viewing progress, and getting personalized coaching.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
visualizing-data
IncludedBuilds dashboards, reports, and data-driven interfaces requiring charts, graphs, or visual analytics. Provides systematic framework for selecting appropriate visualizations based on data characteristics and analytical purpose. Includes 24+ visualization types organized by purpose (trends, comparisons, distributions, relationships, flows, hierarchies, geospatial), accessibility patterns (WCAG 2.1 AA compliance), colorblind-safe palettes, and performance optimization strategies. Use when creating visualizations, choosing chart types, displaying data graphically, or designing data interfaces.