monetization-analyzer
Analyze game concepts for monetization potential, willingness-to-pay, viral mechanics, and revenue generation. Ranks concepts by total monetization score and identifies top revenue opportunities.
- Category: discovered
- Tags: github, community
- Version: 1.0.0
- Author: walid
- Downloads: 0
- GitHub stars: 1
- Updated: 2025-11-21
Download the latest version (v1.0.0) from this page.
SKILL.md
---
name: monetization-analyzer
description: Analyze game concepts for monetization potential, willingness-to-pay, viral mechanics, and revenue generation. Ranks concepts by total monetization score and identifies top revenue opportunities.
---
# Monetization Analyzer Skill
## Purpose
This skill evaluates game concepts to identify the most monetizable opportunities based on:
- **Willingness-to-Pay (WTP)** analysis from market data
- **Viral potential** and organic growth mechanics
- **Revenue model optimization** (premium, F2P, subscription, hybrid)
- **Market demand** and addressable market size
- **Competitive pricing** positioning
- **Lifetime Value (LTV)** projections
**Output**: Ranked list of top 3 most monetizable game concepts with detailed financial projections and go-to-market recommendations.
## When to Use This Skill
Use this skill when you have:
- ✅ Multiple game concepts to evaluate for investment prioritization
- ✅ Market analysis data showing pricing sentiment and willingness-to-pay signals
- ✅ Need to identify which concepts have highest revenue potential
- ✅ Want to optimize monetization models before development
- ✅ Require financial projections for pitch decks or funding proposals
- ✅ Need to validate business model assumptions with market data
## Prerequisites
### Required Input Files
1. **Market Analysis Report** (from `market-analyst` skill)
- Location: `/docs/market-analysis-*.md`
- Must include: Sentiment data on pricing, monetization pain points, willingness-to-pay signals
- Example: `market-analysis-fps-games-2025-10-26.md`
2. **Game Concepts Document** (from brainstorming/design)
- Location: `/docs/*-game-concepts-*.md` or `/docs/plans/*-design.md`
- Must include: Price points, target personas, distribution channels, competitors
- Example: `fps-game-concepts-market-driven-2025-10-26.md`
### Optional Input Files
3. **Competitor Financial Data** (if available)
- Revenue reports, player counts, ARPU data
- Enhances accuracy of projections
## Core Workflow
### Phase 1: Data Extraction and Normalization
**1. Load Market Analysis**
Extract willingness-to-pay signals:
```javascript
WTP_Signals = {
price_sentiment: {
"$0 (F2P)": {positive: X%, negative: Y%, mentions: N},
"$10-20": {positive: X%, negative: Y%, mentions: N},
"$20-30": {positive: X%, negative: Y%, mentions: N},
"$60-70": {positive: X%, negative: Y%, mentions: N},
"$70 + MTX": {positive: X%, negative: Y%, mentions: N}
},
monetization_pain_points: [
{issue: "Premium + battle pass", severity: "CRITICAL", mentions: N},
{issue: "Loot boxes", severity: "HIGH", mentions: N}
],
value_propositions: [
{model: "F2P cosmetic-only", sentiment: X%, examples: []},
{model: "Budget indie ($15-25)", sentiment: X%, examples: []}
]
}
```
**2. Load Game Concepts**
Extract monetization-relevant data for each concept:
```javascript
GameConcept = {
name: string,
price_point: number | "F2P",
monetization_model: string,
target_audience: {
primary_persona: {},
market_size_estimate: number,
spending_behavior: string
},
competitors: [{name, price, model, performance}],
distribution_channels: [{platform, percentage, rationale}],
lifecycle_commitment: string,
development_cost_estimate: number
}
```
### Phase 2: Willingness-to-Pay Analysis
**3. Calculate WTP Score (0-100)**
```javascript
function calculateWTP(concept, marketData) {
const score = {
price_sentiment_alignment: 0, // Does price match positive sentiment tier?
value_perception: 0, // Content/$ ratio vs. market expectations
monetization_model_fit: 0, // Model aligns with audience preferences?
competitive_positioning: 0, // Price competitive advantage?
pain_point_avoidance: 0 // Avoids monetization red flags?
};
// Price Sentiment Alignment (0-30 points)
const priceТier = getPriceTier(concept.price_point);
const sentiment = marketData.price_sentiment[priceTier];
score.price_sentiment_alignment = (sentiment.positive / 100) * 30;
// Value Perception (0-25 points)
const contentHours = estimateContentHours(concept);
const pricePerHour = concept.price_point / contentHours;
const marketAvgPricePerHour = calculateMarketAverage();
if (pricePerHour < marketAvgPricePerHour * 0.8) {
score.value_perception = 25; // Excellent value
} else if (pricePerHour < marketAvgPricePerHour) {
score.value_perception = 18; // Good value
} else if (pricePerHour < marketAvgPricePerHour * 1.2) {
score.value_perception = 10; // Fair value
} else {
score.value_perception = 0; // Poor value
}
// Monetization Model Fit (0-20 points)
const modelSentiment = marketData.value_propositions.find(
vp => vp.model === concept.monetization_model
);
score.monetization_model_fit = (modelSentiment.sentiment / 100) * 20;
// Competitive Positioning (0-15 points)
const competitorPrices = concept.competitors.map(c => c.price);
const avgCompetitorPrice = average(competitorPrices);
if (concept.price_point < avgCompetitorPrice * 0.7) {
score.competitive_positioning = 15; // Undercut leaders
} else if (concept.price_point < avgCompetitorPrice) {
score.competitive_positioning = 10; // Competitive pricing
} else {
score.competitive_positioning = 5; // Premium positioning
}
// Pain Point Avoidance (0-10 points)
const painPoints = marketData.monetization_pain_points;
let violations = 0;
painPoints.forEach(pp => {
if (conceptViolatesPainPoint(concept, pp)) {
violations += (pp.severity === "CRITICAL") ? 5 : 2;
}
});
score.pain_point_avoidance = Math.max(0, 10 - violations);
return {
total: Object.values(score).reduce((a, b) => a + b, 0),
breakdown: score,
confidence: calculateConfidence(marketData.sample_size)
};
}
```
**WTP Score Interpretation:**
- **90-100**: Exceptional WTP, price optimization perfect
- **75-89**: Strong WTP, minor adjustments possible
- **60-74**: Moderate WTP, consider price/model changes
- **Below 60**: Weak WTP, major repositioning needed
### Phase 3: Viral Potential Analysis
**4. Calculate Viral Score (0-100)**
```javascript
function calculateViralPotential(concept, marketData) {
const score = {
shareability: 0, // Content naturally creates shareable moments?
accessibility: 0, // Low barrier to entry?
network_effects: 0, // Benefits from friend invites?
streamer_appeal: 0, // Twitch/YouTube friendly?
novelty_factor: 0, // Unique enough to generate buzz?
social_features: 0 // Built for social play/sharing?
};
// Shareability (0-20 points)
const shareableGenres = ["party game", "asymmetric", "sports hybrid", "roguelike"];
if (shareableGenres.some(g => concept.genre.includes(g))) {
score.shareability = 20;
} else if (concept.genre.includes("competitive") || concept.genre.includes("co-op")) {
score.shareability = 12;
} else {
score.shareability = 5; // Single-player, narrative
}
// Accessibility (0-20 points)
if (concept.price_point === "F2P") {
score.accessibility = 20; // Zero barrier
} else if (concept.price_point <= 15) {
score.accessibility = 15; // Impulse purchase
} else if (concept.price_point <= 25) {
score.accessibility = 10; // Reasonable
} else {
score.accessibility = 5; // Higher barrier
}
// Network Effects (0-20 points)
if (concept.monetization_model.includes("F2P") || concept.monetization_model.includes("viral")) {
score.network_effects = 20;
} else if (concept.description.includes("co-op") || concept.description.includes("multiplayer")) {
score.network_effects = 12;
} else {
score.network_effects = 0;
}
// Streamer Appeal (0-15 points)
const streamerFriendly = [
concept.genre.includes("asymmetric"),
concept.genre.includes("roguelike"),
concept.genre.includes("party"),
concept.description.includes("viral moments"),
concept.description.includes("spectator")
];
score.streamer_appeal = streamerFriendly.filter(Boolean).length * 3;
// Novelty Factor (0-15 points)
const noveltyIndicators = marketData.novelty_successes || [];
if (noveltyIndicators.some(n => concept.description.includes(n.innovation))) {
score.novelty_factor = 15;
} else if (concept.description.includes("unique") || concept.description.includes("first")) {
score.novelty_factor = 10;
} else {
score.novelty_factor = 5;
}
// Social Features (0-10 points)
const socialKeywords = ["co-op", "multiplayer", "friend", "clan", "team", "squad"];
const socialCount = socialKeywords.filter(kw =>
concept.description.toLowerCase().includes(kw)
).length;
score.social_features = Math.min(10, socialCount * 2);
return {
total: Object.values(score).reduce((a, b) => a + b, 0),
breakdown: score,
viral_coefficient: estimateViralCoefficient(score.total)
};
}
function estimateViralCoefficient(viralScore) {
// Viral coefficient: How many new users does each user bring?
// K > 1 = exponential growth, K < 1 = paid acquisition needed
if (viralScore >= 85) return 1.5; // Exceptional viral growth
if (viralScore >= 70) return 1.2; // Strong organic growth
if (viralScore >= 55) return 0.8; // Some viral mechanics
if (viralScore >= 40) return 0.4; // Minimal viral spread
return 0.2; // Requires paid marketing
}
```
**Viral Score Interpretation:**
- **85-100**: Viral hit potential (K > 1.2), minimal marketing spend
- **70-84**: Strong organic growth (K ~1.0), word-of-mouth driven
- **55-69**: Moderate virality (K ~0.8), some paid marketing needed
- **40-54**: Low virality (K ~0.4), heavy marketing investment required
- **Below 40**: No viral mechanics (K ~0.2), paid acquisition only
### Phase 4: Revenue Projection Modeling
**5. Calculate Revenue Potential (Year 1-3 Projections)**
```javascript
function projectRevenue(concept, wtpScore, viralScore, marketData) {
const model = concept.monetization_model;
// Addressable Market Size
const TAM = estimateTotalAddressableMarket(concept, marketData);
const SAM = TAM * 0.15; // Serviceable addressable (15% of TAM realistic)
const SOM = SAM * getMarketShareEstimate(viralScore, concept.competitors.length);
// Player Acquisition Model
const year1Players = calculateYear1Players(concept, viralScore, SOM);
const year2Players = year1Players * getRetentionMultiplier(concept.lifecycle_commitment);
const year3Players = year2Players * getGrowthMultiplier(viralScore);
// Revenue Calculations
if (model.includes("F2P")) {
return projectF2PRevenue(year1Players, year2Players, year3Players, concept);
} else if (model.includes("premium") || typeof concept.price_point === "number") {
return projectPremiumRevenue(year1Players, year2Players, year3Players, concept);
} else {
return projectHybridRevenue(year1Players, year2Players, year3Players, concept);
}
}
function projectF2PRevenue(y1Players, y2Players, y3Players, concept) {
// F2P Model: Base * Conversion Rate * ARPPU
const conversionRate = 0.03; // Industry avg: 3-5% pay
const ARPPU = estimateARPPU(concept); // Average revenue per paying user
const y1Revenue = y1Players * conversionRate * ARPPU;
const y2Revenue = y2Players * (conversionRate * 1.1) * (ARPPU * 1.15); // Improve over time
const y3Revenue = y3Players * (conversionRate * 1.15) * (ARPPU * 1.25);
return {
year1: {players: y1Players, revenue: y1Revenue, ARPU: y1Revenue / y1Players},
year2: {players: y2Players, revenue: y2Revenue, ARPU: y2Revenue / y2Players},
year3: {players: y3Players, revenue: y3Revenue, ARPU: y3Revenue / y3Players},
total_3yr: y1Revenue + y2Revenue + y3Revenue,
LTV: (y1Revenue + y2Revenue + y3Revenue) / y1Players
};
}
function projectPremiumRevenue(y1Players, y2Players, y3Players, concept) {
// Premium Model: Units Sold * Price + Optional DLC
const basePrice = concept.price_point;
const dlcAttachRate = 0.25; // 25% buy DLC
const avgDLCSpend = basePrice * 0.6; // DLC ~60% of base price
const y1Revenue = (y1Players * basePrice) + (y1Players * dlcAttachRate * avgDLCSpend * 0.5);
const y2Revenue = (y2Players * 0.3 * basePrice) + (y2Players * 0.3 * dlcAttachRate * avgDLCSpend);
const y3Revenue = (y3Players * 0.1 * basePrice) + (y3Players * 0.1 * dlcAttachRate * avgDLCSpend);
return {
year1: {players: y1Players, revenue: y1Revenue, ARPU: basePrice},
year2: {players: y2Players * 0.3, revenue: y2Revenue, ARPU: basePrice},
year3: {players: y3Players * 0.1, revenue: y3Revenue, ARPU: basePrice},
total_3yr: y1Revenue + y2Revenue + y3Revenue,
LTV: basePrice + (dlcAttachRate * avgDLCSpend)
};
}
function estimateARPPU(concept) {
// Average Revenue Per Paying User (F2P)
if (concept.genre.includes("competitive")) return 45; // Esports skin buyers spend more
if (concept.genre.includes("party")) return 20; // Casual spenders
if (concept.genre.includes("co-op")) return 30; // Mid-tier
return 25; // Default
}
function estimateTotalAddressableMarket(concept, marketData) {
// Use market analysis data + platform data
const steamActivePlayers = 120000000; // ~120M monthly active on Steam
const genreMultiplier = getGenreMarketShare(concept.genre);
return steamActivePlayers * genreMultiplier;
}
function getMarketShareEstimate(viralScore, competitorCount) {
// Viral potential + competitive landscape determines realistic share
let baseShare = 0.01; // 1% of SAM baseline
if (viralScore >= 85) baseShare *= 3; // Viral hit
else if (viralScore >= 70) baseShare *= 2; // Strong growth
else if (viralScore >= 55) baseShare *= 1.5;
// Competitive penalty
if (competitorCount > 5) baseShare *= 0.7;
else if (competitorCount > 3) baseShare *= 0.85;
return baseShare;
}
```
**6. Calculate Development ROI**
```javascript
function calculateROI(concept, revenueProjection) {
const devCost = concept.development_cost_estimate || estimateDevCost(concept);
const marketingCost = estimateMarketingCost(concept, revenueProjection.year1.players);
const totalInvestment = devCost + marketingCost;
const grossRevenue = revenueProjection.total_3yr;
const platformFees = grossRevenue * 0.30; // Steam/console take 30%
const netRevenue = grossRevenue - platformFees;
const netProfit = netRevenue - totalInvestment;
return {
investment: totalInvestment,
gross_revenue: grossRevenue,
net_revenue: netRevenue,
net_profit: netProfit,
ROI_percentage: (netProfit / totalInvestment) * 100,
payback_period_months: calculatePaybackPeriod(totalInvestment, revenueProjection),
break_even_units: totalInvestment / (concept.price_point || 25)
};
}
function estimateDevCost(concept) {
// Based on scope, team size, timeline
if (concept.description.includes("solo") || concept.description.includes("small team")) {
return 150000; // $150K
} else if (concept.description.includes("128-player") || concept.description.includes("large-scale")) {
return 8000000; // $8M
} else {
return 1200000; // $1.2M (AA indie default)
}
}
function estimateMarketingCost(concept, year1Players) {
// Cost per acquisition based on viral coefficient
const viralCoef = concept.viral_coefficient || 0.5;
if (viralCoef >= 1.2) {
// Viral growth, minimal paid marketing
return year1Players * 0.50; // $0.50 CPA (mostly organic)
} else if (viralCoef >= 0.8) {
return year1Players * 2; // $2 CPA
} else {
return year1Players * 5; // $5 CPA (heavy paid)
}
}
```
### Phase 5: Monetization Optimization Recommendations
**7. Analyze Monetization Model Fit**
```javascript
function analyzeMonetizationModel(concept, wtpScore, viralScore, marketData) {
const currentModel = concept.monetization_model;
const alternativeModels = [];
// Test F2P vs. Premium
if (currentModel.includes("premium") && viralScore >= 70) {
alternativeModels.push({
model: "F2P with cosmetic monetization",
rationale: `High viral score (${viralScore}) suggests F2P could 5-10x player base`,
projected_revenue_delta: "+40-80%",
risk: "ARPPU uncertainty, requires cosmetic art pipeline"
});
}
// Test pricing tiers
if (typeof concept.price_point === "number") {
const sentiment = marketData.price_sentiment;
const currentTier = getPriceTier(concept.price_point);
Object.keys(sentiment).forEach(tier => {
if (tier !== currentTier && sentiment[tier].positive > sentiment[currentTier].positive + 10) {
alternativeModels.push({
model: `Price adjustment to ${tier}`,
rationale: `${tier} has ${sentiment[tier].positive}% positive vs. current ${sentiment[currentTier].positive}%`,
projected_revenue_delta: estimatePriceChangeDelta(concept, tier),
risk: "Value perception vs. content ratio"
});
}
});
}
// Test monetization add-ons
if (!currentModel.includes("DLC") && concept.lifecycle_commitment.includes("2-3 year")) {
alternativeModels.push({
model: "Add expansion DLC model",
rationale: "Long lifecycle supports premium content drops",
projected_revenue_delta: "+15-25%",
risk: "Community expectations for free updates"
});
}
return {
current_model: currentModel,
current_model_score: scoreMonetizationModel(currentModel, wtpScore, viralScore),
alternatives: alternativeModels.sort((a, b) =>
parseFloat(b.projected_revenue_delta) - parseFloat(a.projected_revenue_delta)
)
};
}
```
### Phase 6: Composite Monetization Score & Ranking
**8. Calculate Total Monetization Score (0-100)**
```javascript
function calculateMonetizationScore(concept, wtpScore, viralScore, revenueProjection, roi) {
const score = {
willingness_to_pay: wtpScore.total * 0.25, // 25% weight
viral_potential: viralScore.total * 0.20, // 20% weight
revenue_potential: normalizeRevenue(revenueProjection.total_3yr) * 0.30, // 30% weight
roi_efficiency: normalizeROI(roi.ROI_percentage) * 0.15, // 15% weight
time_to_profit: normalizePaybackPeriod(roi.payback_period_months) * 0.10 // 10% weight
};
return {
total: Object.values(score).reduce((a, b) => a + b, 0),
breakdown: score,
tier: getMonetizationTier(Object.values(score).reduce((a, b) => a + b, 0))
};
}
function normalizeRevenue(revenue) {
// Normalize to 0-100 scale (assuming $50M = 100)
return Math.min(100, (revenue / 50000000) * 100);
}
function normalizeROI(roiPercentage) {
// Normalize to 0-100 scale (500% ROI = 100)
return Math.min(100, (roiPercentage / 500) * 100);
}
function normalizePaybackPeriod(months) {
// Shorter = better (6 months = 100, 36 months = 0)
return Math.max(0, 100 - ((months - 6) / 30) * 100);
}
function getMonetizationTier(score) {
if (score >= 90) return "S-TIER: Blockbuster potential";
if (score >= 80) return "A-TIER: Strong monetization";
if (score >= 70) return "B-TIER: Solid revenue opportunity";
if (score >= 60) return "C-TIER: Moderate monetization";
return "D-TIER: Weak monetization";
}
```
**9. Rank and Select Top 3**
```javascript
function rankConcepts(concepts, scores) {
const ranked = concepts.map((concept, i) => ({
concept: concept,
scores: scores[i],
monetization_score: scores[i].total,
recommendation: generateRecommendation(concept, scores[i])
})).sort((a, b) => b.monetization_score - a.monetization_score);
return {
top3: ranked.slice(0, 3),
all_ranked: ranked,
summary: generateRankingSummary(ranked)
};
}
function generateRecommendation(concept, scores) {
const strengths = [];
const weaknesses = [];
const actions = [];
// Analyze strengths
if (scores.breakdown.willingness_to_pay >= 20) strengths.push("Strong price/value fit");
if (scores.breakdown.viral_potential >= 16) s