Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Growth engineering - PLG, referral, viral loops, onboarding optimization.
.claude/skills/growth-engineering/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 167% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 206% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 288% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 191% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 247% | 0% |
User Signs Up (Free)
|
v
Experiences Value (Aha Moment)
|
v
Invites Team/Colleagues
|
v
Team Adopts Product
|
v
Usage Grows -> Hits Limits
|
v
Converts to Paid
|
v
Expands (More Seats/Features)
|
+---> Refers New Users (loop back)typescriptinterface PLGConfig { freeTier: { features: string[]; limits: Record<string, number>; // { projects: 3, members: 5, storage_gb: 1 } duration: "unlimited" | number; // gun cinsinden veya sinirsiz }; trialTier: { features: string[]; duration_days: number; requires_cc: boolean; }; paidTiers: Array<{ name: string; price_monthly: number; price_annual: number; features: string[]; limits: Record<string, number>; }>; gates: FeatureGate[]; } interface FeatureGate { feature: string; gate_type: "hard" | "soft" | "usage"; free_limit?: number; upgrade_prompt: string; cta: string; } // Feature gate middleware function checkFeatureGate(feature: string) { return async (req: Request, res: Response, next: NextFunction) => { const user = req.user; const gate = gates.find(g => g.feature === feature); if (!gate) return next(); const plan = await getUserPlan(user.id); const usage = await getFeatureUsage(user.id, feature); if (gate.gate_type === "hard" && plan.tier === "free") { return res.status(403).json({ error: "UPGRADE_REQUIRED", message: gate.upgrade_prompt, cta: gate.cta, upgrade_url: `/billing/upgrade?feature=${feature}`, }); } if (gate.gate_type === "usage" && gate.free_limit && usage >= gate.free_limit) { // Soft limit: izin ver ama uyar res.setHeader("X-Usage-Warning", gate.upgrade_prompt); await trackEvent(user.id, "feature_gate_hit", { feature, usage, limit: gate.free_limit }); } next(); }; }
| Urun Tipi | Aha Moment Ornegi | Metrik | |-----------|-------------------|--------| | Project Management | Ilk task'i tamamlama | task_completed (first) | | Analytics | Ilk dashboard olusturma | dashboard_created (first) | | Communication | Ilk mesaj gonderme | message_sent (first) | | Development Tool | Ilk basarili build | build_succeeded (first) | | Design Tool | Ilk export/share | design_exported (first) |
typescriptinterface AhaMoment { event: string; conditions: Record<string, unknown>; time_window_hours: number; // Bu sure icinde olursa "activated" activation_rate_target: number; // %40-60 hedef } const ahaMoment: AhaMoment = { event: "project_created_with_members", conditions: { member_count: { gte: 2 }, tasks_added: { gte: 3 } }, time_window_hours: 72, // Kayittan sonra 72 saat icinde activation_rate_target: 0.50, };
typescriptinterface ReferralProgram { id: string; name: string; reward_type: "two_sided" | "referrer_only" | "referee_only"; referrer_reward: Reward; referee_reward: Reward; rules: ReferralRules; } interface Reward { type: "credit" | "discount" | "free_months" | "feature_unlock" | "cash"; amount: number; currency?: string; description: string; } interface ReferralRules { max_referrals_per_user: number; // spam onleme qualification_event: string; // ne zaman odul verilir qualification_window_days: number; // sure siniri anti_fraud: AntiFraudRules; } interface AntiFraudRules { same_ip_block: boolean; email_domain_block: string[]; // disposable email engelle min_activity_threshold: number; // minimum kullanim cooldown_hours: number; // ayni kisi icin bekleme }
Referrer Referee
| |
|-- Shares unique link --------> |
| |-- Signs up
| |-- Completes qualification
| | (first purchase / activation)
|<-- Notification: Reward! ------|
|-- Reward credited |-- Reward credited
| |
v v
Track: referral_completed Track: referred_user_activatedsqlCREATE TABLE referrals ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), referrer_id UUID NOT NULL REFERENCES users(id), referee_id UUID REFERENCES users(id), referral_code VARCHAR(20) UNIQUE NOT NULL, referral_link TEXT NOT NULL, status VARCHAR(20) DEFAULT 'pending', -- pending, signed_up, qualified, rewarded, expired channel VARCHAR(50), -- email, social, direct_link created_at TIMESTAMPTZ DEFAULT NOW(), signed_up_at TIMESTAMPTZ, qualified_at TIMESTAMPTZ, rewarded_at TIMESTAMPTZ, referrer_reward_amount DECIMAL, referee_reward_amount DECIMAL, metadata JSONB DEFAULT '{}' ); CREATE INDEX idx_referrals_referrer ON referrals(referrer_id); CREATE INDEX idx_referrals_code ON referrals(referral_code); CREATE INDEX idx_referrals_status ON referrals(status); -- Referral metrikleri SELECT referrer_id, COUNT(*) AS total_referrals, COUNT(CASE WHEN status = 'signed_up' THEN 1 END) AS signups, COUNT(CASE WHEN status = 'qualified' THEN 1 END) AS qualified, COUNT(CASE WHEN status = 'rewarded' THEN 1 END) AS rewarded, ROUND(100.0 * COUNT(CASE WHEN status = 'qualified' THEN 1 END) / NULLIF(COUNT(CASE WHEN status = 'signed_up' THEN 1 END), 0), 1) AS conversion_rate FROM referrals GROUP BY referrer_id ORDER BY qualified DESC;
| Tip | Mekanizma | Ornek | K-Factor Hedef | |-----|-----------|-------|---------------| | Word of Mouth | Organik tavsiye | Slack, Notion | 0.3-0.5 | | Incentivized | Odul ile tavsiye | Dropbox (500MB) | 0.5-0.8 | | Embedded | Urunde gorulme | "Made with X" | 0.2-0.4 | | Collaborative | Birlikte kullanim | Google Docs invite | 0.6-1.0 | | Social Proof | Paylasim/showcase | Spotify Wrapped | 0.3-0.6 | | Content | Icerik uretimi | Canva, Figma links | 0.2-0.4 |
typescriptinterface ViralMetrics { invites_per_user: number; // ortalama gonderilen davet invite_conversion_rate: number; // davetin kabul orani cycle_time_days: number; // bir loop'un suresi } function calculateKFactor(metrics: ViralMetrics): { kFactor: number; viral: boolean; doublingTimeDays: number | null; } { // K = invites_per_user * conversion_rate const k = metrics.invites_per_user * metrics.invite_conversion_rate; return { kFactor: Math.round(k * 100) / 100, viral: k > 1, // K > 1 = organik buyume doublingTimeDays: k > 1 ? Math.round(metrics.cycle_time_days * Math.log(2) / Math.log(k)) : null, }; } // Ornek: 3 invite * %25 conversion = K=0.75 (viral degil ama katkisi var) // Ornek: 5 invite * %30 conversion = K=1.5 (viral!)
typescript// "Made with [Product]" badge (embedded viral loop) function generateShareableBadge(projectId: string, userId: string): string { const trackingUrl = `https://app.example.com/r/${encodeBase64(userId)}?ref=badge&project=${projectId}`; return ` <a href="${trackingUrl}" target="_blank" rel="noopener"> <img src="https://app.example.com/badge.svg" alt="Made with Example" width="120" height="28" /> </a> `; } // Collaborative viral loop async function inviteToProject( inviterId: string, projectId: string, emails: string[] ): Promise<InviteResult[]> { const results: InviteResult[] = []; for (const email of emails) { // Rate limit: max 10 invite per project per day const todayInvites = await getInviteCount(inviterId, projectId, "today"); if (todayInvites >= 10) { results.push({ email, status: "rate_limited" }); continue; } const invite = await createInvite({ inviterId, projectId, email }); await sendInviteEmail(email, invite); await trackEvent(inviterId, "invite_sent", { project_id: projectId, invite_id: invite.id, channel: "email", }); results.push({ email, status: "sent", invite_id: invite.id }); } return results; }
typescriptinterface OnboardingStep { id: string; title: string; description: string; action_type: "auto" | "user_action" | "integration"; completion_event: string; required: boolean; order: number; estimated_minutes: number; help_url?: string; } const onboardingSteps: OnboardingStep[] = [ { id: "profile", title: "Profilini tamamla", description: "Adini ve rol bilgini ekle", action_type: "user_action", completion_event: "profile_completed", required: true, order: 1, estimated_minutes: 1, }, { id: "first_project", title: "Ilk projeyi olustur", description: "Bir proje olusturup calismaya basla", action_type: "user_action", completion_event: "project_created", required: true, order: 2, estimated_minutes: 2, }, { id: "invite_team", title: "Takimini davet et", description: "En az 1 takim arkadasi ekle", action_type: "user_action", completion_event: "team_member_invited", required: false, order: 3, estimated_minutes: 2, }, { id: "integration", title: "Entegrasyon bagla", description: "GitHub, Slack veya Jira bagla", action_type: "integration", completion_event: "integration_connected", required: false, order: 4, estimated_minutes: 3, }, ]; // Onboarding progress tracker async function getOnboardingProgress(userId: string): Promise<{ completed: string[]; remaining: OnboardingStep[]; percentage: number; nextStep: OnboardingStep | null; }> { const completedEvents = await getUserEvents(userId, onboardingSteps.map(s => s.completion_event)); const completed = onboardingSteps .filter(s => completedEvents.includes(s.completion_event)) .map(s => s.id); const remaining = onboardingSteps.filter(s => !completed.includes(s.id)); return { completed, remaining, percentage: Math.round((completed.length / onboardingSteps.length) * 100), nextStep: remaining[0] || null, }; }
| Metrik | Formul | Hedef | |--------|--------|-------| | Completion Rate | completed_all_steps / started_onboarding | > %60 | | Time to Complete | median(onboarding_end - signup) | < 10 dakika | | Drop-off Point | En cok terk edilen adim | Her adim > %80 | | Activation Rate | aha_moment_reached / signed_up | > %40 | | Time to Value | signup -> first_value_event | < 5 dakika |
typescript// Engagement-based onboarding (her seyi birden gosterme) interface OnboardingTrigger { feature: string; show_after: string; // event sonrasi goster delay_seconds: number; tooltip_position: "top" | "bottom" | "left" | "right"; message: string; dismiss_event: string; } const progressiveHints: OnboardingTrigger[] = [ { feature: "keyboard_shortcuts", show_after: "third_task_created", delay_seconds: 2, tooltip_position: "bottom", message: "Pro tip: Ctrl+K ile hizli komut menusunu acabilirsin", dismiss_event: "shortcut_hint_dismissed", }, { feature: "automation", show_after: "tenth_task_completed", delay_seconds: 5, tooltip_position: "right", message: "Bu tekrarlayan gorevi otomatiklestirmek ister misin?", dismiss_event: "automation_hint_dismissed", }, ];
Signup --> Setup --> Aha Moment --> Habit
| | | |
v v v v
100% ~70% ~40% ~20%typescriptinterface ActivationCriteria { name: string; events: Array<{ event: string; count: number; // minimum kac kez within_days: number; // kac gun icinde }>; logic: "AND" | "OR"; // tum kriterler mi, herhangi biri mi } const activationDefinitions: ActivationCriteria[] = [ { name: "basic_activation", events: [ { event: "project_created", count: 1, within_days: 3 }, { event: "task_created", count: 3, within_days: 7 }, ], logic: "AND", }, { name: "team_activation", events: [ { event: "team_member_invited", count: 1, within_days: 7 }, { event: "collaborative_action", count: 5, within_days: 14 }, ], logic: "AND", }, ]; // Hangi activation definition en iyi retention ile korelasyon gosteriyor? // -> A/B test et, D30 retention ile karsilastir
| Strateji | Sinir Tipi | Ornek | |----------|-----------|-------| | Feature-limited | Bazi ozellikler locked | Slack (mesaj gecmisi), GitHub (private repo) | | Usage-limited | Kullanim siniri | Dropbox (2GB), Vercel (100GB bandwidth) | | Seat-limited | Kullanici sayisi | Notion (10 guest), Linear (10 members) | | Time-limited (trial) | Sure siniri | 14 gun full access | | Support-limited | Destek seviyesi | Community vs Priority support |
typescriptinterface PricingExperiment { name: string; hypothesis: string; variants: Array<{ id: string; change: string; expected_impact: string; }>; primary_metric: string; } const pricingExperiments: PricingExperiment[] = [ { name: "anchor_pricing", hypothesis: "Enterprise plani one koymak, Pro plan conversion'i %15 arttirir", variants: [ { id: "control", change: "Free -> Pro -> Enterprise", expected_impact: "baseline" }, { id: "treatment", change: "Enterprise -> Pro -> Free (reverse)", expected_impact: "+15% Pro conversion" }, ], primary_metric: "plan_upgrade_rate", }, { name: "annual_discount", hypothesis: "%20 yerine 2 ay bedava demek, annual conversion'i %10 arttirir", variants: [ { id: "control", change: "Save 20%", expected_impact: "baseline" }, { id: "treatment", change: "2 months free", expected_impact: "+10% annual" }, ], primary_metric: "annual_plan_rate", }, ];
Idea -> Prioritize (ICE) -> Design -> Implement -> Run -> Analyze -> Learntypescriptinterface GrowthExperiment { id: string; name: string; hypothesis: string; impact: number; // 1-10: basarili olursa ne kadar etki confidence: number; // 1-10: basarili olma ihtimali ease: number; // 1-10: ne kadar kolay implement ice_score: number; // (impact + confidence + ease) / 3 primary_metric: string; status: "backlog" | "designing" | "running" | "analyzing" | "completed"; results?: ExperimentResult; } function prioritizeExperiments(experiments: GrowthExperiment[]): GrowthExperiment[] { return experiments .map(e => ({ ...e, ice_score: (e.impact + e.confidence + e.ease) / 3, })) .sort((a, b) => b.ice_score - a.ice_score); }
typescriptinterface ExperimentResult { experiment_id: string; start_date: string; end_date: string; sample_size: { control: number; treatment: number }; primary_metric: { control_value: number; treatment_value: number; lift: number; // % p_value: number; significant: boolean; }; secondary_metrics: Array<{ name: string; lift: number; significant: boolean; }>; decision: "ship" | "iterate" | "kill"; learnings: string[]; }
typescriptinterface NotificationConfig { type: "push" | "email" | "in_app" | "sms"; trigger: string; // event name template: string; delay_minutes: number; frequency_cap: { max_per_day: number; max_per_week: number; }; segment: string; // user segment priority: "critical" | "high" | "medium" | "low"; } const notificationSchedule: NotificationConfig[] = [ // Onboarding sequence { type: "email", trigger: "user_signed_up", template: "welcome_email", delay_minutes: 0, frequency_cap: { max_per_day: 1, max_per_week: 3 }, segment: "new_users", priority: "high", }, { type: "email", trigger: "onboarding_incomplete_24h", template: "complete_setup_nudge", delay_minutes: 24 * 60, frequency_cap: { max_per_day: 1, max_per_week: 2 }, segment: "incomplete_onboarding", priority: "medium", }, // Re-engagement { type: "email", trigger: "inactive_7_days", template: "we_miss_you", delay_minutes: 0, frequency_cap: { max_per_day: 1, max_per_week: 1 }, segment: "churning", priority: "medium", }, // Expansion { type: "in_app", trigger: "usage_limit_80_percent", template: "upgrade_nudge", delay_minutes: 0, frequency_cap: { max_per_day: 1, max_per_week: 2 }, segment: "high_usage_free", priority: "high", }, ];
| Pattern | Mekanizma | Ornek | |---------|-----------|-------| | Variable Reward | Beklenmedik oduller | LinkedIn: "X viewed your profile" | | Investment | Kullanici emek harcayor | Pinterest: pin boards | | Social Proof | Baskalari kullaniyor | "1000+ team already uses..." | | Progress | Ilerleme gosterimi | Duolingo streak | | Commitment | Kucuk adimlar -> buyuk adimlar | Free trial -> paid | | Loss Aversion | Kaybetme korkusu | "Your streak will reset!" | | FOMO | Kacirma korkusu | "Limited time offer" |
typescriptinterface StreakConfig { activity_event: string; period: "daily" | "weekly"; milestones: Array<{ days: number; reward: string; badge?: string; }>; grace_period_hours: number; // streak kurtarma suresi freeze_available: boolean; // streak dondurma hakki } const streakConfig: StreakConfig = { activity_event: "daily_active", period: "daily", milestones: [ { days: 3, reward: "Nice start!", badge: "streak_3" }, { days: 7, reward: "1 week streak!", badge: "streak_7" }, { days: 30, reward: "Monthly warrior!", badge: "streak_30" }, { days: 100, reward: "Centurion!", badge: "streak_100" }, ], grace_period_hours: 12, freeze_available: true, };
| Anti-Pattern | Dogru Yol | |-------------|-----------| | Feature gating cok agresif | Deger gorsun, sonra gate koy | | Spam notification | Frequency cap + unsubscribe kolay | | Karisik onboarding | Max 5 adim, progressive disclosure | | Referral odulunu geciktirmek | Aninda ver, sonra qualify et | | K-Factor'u ignore etmek | Her feature'da viral loop dusun | | Tek seferlik onboarding | Devam eden egitim (progressive) | | Agresif upgrade prompt | Deger gordukleri anda goster | | Tum kullanicilara ayni deneyim | Segment-based kisiselllestirme |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | fail→pass | 16,188 | 17,338 | +7% | 1 | 1 | 0% | 3,636 | 9,709 | +167% | 0 | 0 | — |
case-03 | fail→pass | 11,452 | 9,707 | -15% | 1 | 1 | 0% | 2,588 | 7,908 | +206% | 0 | 0 | — |
case-02 | fail→fail | 21,660 | 12,759 | -41% | 1 | 1 | 0% | 2,988 | 8,883 | +197% | 0 | 0 | — |
case-01 | fail→fail | 9,619 | 9,133 | -5% | 1 | 1 | 0% | 1,977 | 7,915 | +300% | 0 | 0 | — |
case-05 | fail→pass | 9,392 | 5,397 | -43% | 1 | 1 | 0% | 1,781 | 6,910 | +288% | 0 | 0 | — |
case-06 | fail→fail | 12,326 | 14,904 | +21% | 1 | 1 | 0% | 2,436 | 8,762 | +260% | 0 | 0 | — |
case-07 | pass→pass | 14,943 | 14,925 | -0% | 1 | 1 | 0% | 3,256 | 9,178 | +182% | 0 | 0 | — |
case-08 | pass→pass | 10,373 | 10,432 | +1% | 1 | 1 | 0% | 2,262 | 8,182 | +262% | 0 | 0 | — |
case-09 | pass→pass | 13,706 | 16,526 | +21% | 1 | 1 | 0% | 2,565 | 9,348 | +264% | 0 | 0 | — |
case-10 | fail→fail | 13,435 | 13,510 | +1% | 1 | 1 | 0% | 2,677 | 8,619 | +222% | 0 | 0 | — |
case-11 | pass→fail | 11,883 | 13,554 | +14% | 1 | 1 | 0% | 2,286 | 8,152 | +257% | 0 | 0 | — |
case-12 | fail→fail | 11,922 | 11,992 | +1% | 1 | 1 | 0% | 2,374 | 8,565 | +261% | 0 | 0 | — |
case-13 | fail→fail | 15,319 | 10,275 | -33% | 1 | 1 | 0% | 3,167 | 8,205 | +159% | 0 | 0 | — |
case-14 | fail→pass | 14,418 | 12,686 | -12% | 1 | 1 | 0% | 2,958 | 8,608 | +191% | 0 | 0 | — |
case-15 | pass→pass | 13,889 | 7,863 | -43% | 1 | 1 | 0% | 2,690 | 7,499 | +179% | 0 | 0 | — |
case-16 | fail→pass | 16,952 | 20,590 | +21% | 1 | 1 | 0% | 2,747 | 9,543 | +247% | 0 | 0 | — |
case-17 | fail→fail | 17,950 | 10,068 | -44% | 1 | 1 | 0% | 3,759 | 7,795 | +107% | 0 | 0 | — |
case-18 | fail→fail | 16,443 | 8,796 | -47% | 1 | 1 | 0% | 3,541 | 7,612 | +115% | 0 | 0 | — |
case-19 | pass→pass | 14,360 | 23,001 | +60% | 1 | 1 | 0% | 2,649 | 10,187 | +285% | 0 | 0 | — |
case-20 | pass→pass | 15,365 | 9,594 | -38% | 1 | 1 | 0% | 2,418 | 7,665 | +217% | 0 | 0 | — |
case-21 | pass→pass | 13,002 | 14,042 | +8% | 1 | 1 | 0% | 2,730 | 8,844 | +224% | 0 | 0 | — |
case-22 | pass→pass | 14,354 | 15,707 | +9% | 1 | 1 | 0% | 2,784 | 9,213 | +231% | 0 | 0 | — |
case-23 | pass→pass | 13,003 | 12,338 | -5% | 1 | 1 | 0% | 2,967 | 8,525 | +187% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +17 percentage points is the difference between those two pass rates over the 23 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 7/29/2026 | +36% |
Other measured skills in the registry, with their headline benchmark lift.