Claude Code Plugins

Community-maintained marketplace

Feedback

monetization-strategies

@chriscarterux/chris-claude-stack
1
0

This skill should be used when designing revenue models - choosing between freemium, subscriptions, usage-based pricing, ads, enterprise licensing, and hybrid approaches.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name monetization-strategies
description This skill should be used when designing revenue models - choosing between freemium, subscriptions, usage-based pricing, ads, enterprise licensing, and hybrid approaches.

Monetization Strategies

Overview

Effective monetization balances three critical factors: value extraction, user experience, and market expectations. The right revenue model aligns with your product's value delivery pattern, user psychology, and competitive landscape. In 6-day sprints, choosing the optimal monetization strategy early prevents costly pivots and accelerates time-to-revenue.

Core Principle: Charge based on the value metric that grows with customer success, minimizes friction, and creates predictable revenue streams.

When to Use

Use this skill when you need to:

  • Design initial pricing strategy for a new product
  • Optimize existing monetization that's underperforming
  • Evaluate model changes (e.g., free to freemium to paid-only)
  • Set pricing tiers and feature distribution
  • Implement payment infrastructure rapidly
  • A/B test pricing variations to maximize conversion
  • Transition between business models (pivot scenarios)
  • Calculate unit economics and LTV:CAC ratios
  • Design enterprise vs self-serve pricing
  • Choose payment providers and integration patterns

Monetization Models

Freemium

Feature-Gated Freemium

  • Free tier has limited features
  • Premium unlocks advanced capabilities
  • Best for: Productivity tools, SaaS platforms
// Feature gate implementation
interface PlanLimits {
  plan: 'free' | 'pro' | 'enterprise';
  maxProjects: number;
  allowsAdvancedAnalytics: boolean;
  allowsTeamCollaboration: boolean;
  apiCallsPerMonth: number;
}

const PLAN_LIMITS: Record<string, PlanLimits> = {
  free: {
    plan: 'free',
    maxProjects: 3,
    allowsAdvancedAnalytics: false,
    allowsTeamCollaboration: false,
    apiCallsPerMonth: 1000
  },
  pro: {
    plan: 'pro',
    maxProjects: 50,
    allowsAdvancedAnalytics: true,
    allowsTeamCollaboration: true,
    apiCallsPerMonth: 50000
  },
  enterprise: {
    plan: 'enterprise',
    maxProjects: Infinity,
    allowsAdvancedAnalytics: true,
    allowsTeamCollaboration: true,
    apiCallsPerMonth: Infinity
  }
};

function canAccessFeature(user: User, feature: keyof PlanLimits): boolean {
  const limits = PLAN_LIMITS[user.plan];
  return !!limits[feature];
}

Usage-Gated Freemium

  • Free tier has limited usage
  • Premium removes constraints
  • Best for: API services, storage, compute
# Usage tracking for freemium
class UsageGate:
    def __init__(self, user_id, plan):
        self.user_id = user_id
        self.plan = plan
        self.limits = {
            'free': {'requests': 1000, 'storage_gb': 5},
            'starter': {'requests': 10000, 'storage_gb': 50},
            'pro': {'requests': 100000, 'storage_gb': 500},
            'unlimited': {'requests': float('inf'), 'storage_gb': float('inf')}
        }

    def check_usage(self, resource_type):
        current_usage = self.get_current_usage(resource_type)
        limit = self.limits[self.plan][resource_type]

        if current_usage >= limit:
            return {
                'allowed': False,
                'reason': f'{resource_type}_limit_exceeded',
                'current': current_usage,
                'limit': limit,
                'upgrade_required': True
            }

        return {
            'allowed': True,
            'remaining': limit - current_usage,
            'usage_percent': (current_usage / limit) * 100
        }

Subscriptions

Tiered Subscription Pricing

Tier Price Target User Key Features
Starter $9/mo Individual Basic features, 1 user
Pro $29/mo Small teams Advanced features, 5 users
Business $99/mo Growing companies All features, 20 users
Enterprise Custom Large orgs Unlimited, SLA, custom integration

Implementation Pattern (Stripe)

// Stripe subscription setup
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

async function createSubscription(customerId, priceId, trialDays = 14) {
  try {
    const subscription = await stripe.subscriptions.create({
      customer: customerId,
      items: [{ price: priceId }],
      trial_period_days: trialDays,
      payment_behavior: 'default_incomplete',
      payment_settings: {
        save_default_payment_method: 'on_subscription',
      },
      expand: ['latest_invoice.payment_intent'],
    });

    return {
      subscriptionId: subscription.id,
      clientSecret: subscription.latest_invoice.payment_intent.client_secret,
      status: subscription.status,
      trialEnd: subscription.trial_end,
    };
  } catch (error) {
    throw new Error(`Subscription creation failed: ${error.message}`);
  }
}

// Webhook handler for subscription events
async function handleStripeWebhook(event) {
  switch (event.type) {
    case 'customer.subscription.created':
      await onSubscriptionCreated(event.data.object);
      break;
    case 'customer.subscription.updated':
      await onSubscriptionUpdated(event.data.object);
      break;
    case 'customer.subscription.deleted':
      await onSubscriptionCanceled(event.data.object);
      break;
    case 'invoice.payment_succeeded':
      await onPaymentSucceeded(event.data.object);
      break;
    case 'invoice.payment_failed':
      await onPaymentFailed(event.data.object);
      break;
  }
}

Annual vs Monthly Pricing

  • Annual: 16-20% discount (2-2.4 months free)
  • Improves cash flow and retention
  • Reduces churn touchpoints
// Pricing calculator with annual discount
interface PricingTier {
  name: string;
  monthlyPrice: number;
  annualDiscount: number; // percentage
  features: string[];
}

function calculateAnnualPrice(tier: PricingTier): {
  monthlyTotal: number;
  annualPrice: number;
  savings: number;
  effectiveMonthlyPrice: number;
} {
  const monthlyTotal = tier.monthlyPrice * 12;
  const annualPrice = monthlyTotal * (1 - tier.annualDiscount / 100);
  const savings = monthlyTotal - annualPrice;
  const effectiveMonthlyPrice = annualPrice / 12;

  return {
    monthlyTotal,
    annualPrice,
    savings,
    effectiveMonthlyPrice
  };
}

// Example usage
const proPlan: PricingTier = {
  name: 'Pro',
  monthlyPrice: 29,
  annualDiscount: 20,
  features: ['Advanced analytics', 'Priority support', 'Custom branding']
};

// Result: Annual = $278.40, Save $69.60, Effective $23.20/mo

Usage-Based / Consumption Pricing

Best for: APIs, cloud services, infrastructure Value metric: Requests, compute hours, storage, seats

# Metered billing implementation
class MeteringService:
    def __init__(self, stripe_client):
        self.stripe = stripe_client
        self.price_per_unit = {
            'api_request': 0.001,  # $0.001 per request
            'storage_gb_hour': 0.02,  # $0.02 per GB-hour
            'compute_hour': 0.50  # $0.50 per compute hour
        }

    def record_usage(self, subscription_item_id, quantity, timestamp=None):
        """Record usage for metered billing"""
        return self.stripe.subscription_items.create_usage_record(
            subscription_item_id,
            quantity=quantity,
            timestamp=timestamp or int(time.time()),
            action='increment'  # or 'set' for absolute values
        )

    def calculate_monthly_bill(self, usage_data):
        """Calculate bill based on usage"""
        total = 0
        breakdown = {}

        for resource_type, quantity in usage_data.items():
            if resource_type in self.price_per_unit:
                cost = quantity * self.price_per_unit[resource_type]
                breakdown[resource_type] = {
                    'quantity': quantity,
                    'unit_price': self.price_per_unit[resource_type],
                    'total': cost
                }
                total += cost

        return {
            'total': round(total, 2),
            'breakdown': breakdown,
            'billing_period': self.get_current_period()
        }

    def get_usage_alerts(self, user_id, threshold_percent=80):
        """Alert users approaching usage limits"""
        usage = self.get_user_usage(user_id)
        budget = self.get_user_budget(user_id)

        if usage >= budget * (threshold_percent / 100):
            return {
                'alert': True,
                'current_usage': usage,
                'budget': budget,
                'percent': (usage / budget) * 100,
                'message': f'You have used {usage}% of your budget'
            }
        return {'alert': False}

One-Time Purchases

Best for: Mobile apps, desktop software, digital products

// Swift StoreKit 2 implementation
import StoreKit

class PurchaseManager: ObservableObject {
    @Published var purchasedProductIDs = Set<String>()

    private let productIDs = [
        "com.app.premium_unlock",
        "com.app.pro_features",
        "com.app.lifetime_access"
    ]

    func loadProducts() async throws -> [Product] {
        return try await Product.products(for: productIDs)
    }

    func purchase(_ product: Product) async throws -> Transaction? {
        let result = try await product.purchase()

        switch result {
        case .success(let verification):
            let transaction = try checkVerified(verification)
            await transaction.finish()
            await updatePurchasedProducts()
            return transaction

        case .userCancelled, .pending:
            return nil

        @unknown default:
            return nil
        }
    }

    func checkVerified<T>(_ result: VerificationResult<T>) throws -> T {
        switch result {
        case .unverified:
            throw PurchaseError.failedVerification
        case .verified(let safe):
            return safe
        }
    }
}

In-App Purchases (IAP)

Consumable: Credits, coins, energy (can be repurchased) Non-Consumable: Permanent unlocks (one-time) Auto-Renewable Subscriptions: Weekly, monthly, annual Non-Renewing Subscriptions: Fixed duration

// Android Google Play Billing implementation
class BillingManager(private val activity: Activity) {
    private lateinit var billingClient: BillingClient

    fun initializeBilling() {
        billingClient = BillingClient.newBuilder(activity)
            .setListener { billingResult, purchases ->
                if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) {
                    for (purchase in purchases) {
                        handlePurchase(purchase)
                    }
                }
            }
            .enablePendingPurchases()
            .build()

        billingClient.startConnection(object : BillingClientStateListener {
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                if (billingResult.responseCode == BillingResponseCode.OK) {
                    queryProducts()
                }
            }
            override fun onBillingServiceDisconnected() {
                // Retry connection
            }
        })
    }

    fun queryProducts() {
        val productList = listOf(
            QueryProductDetailsParams.Product.newBuilder()
                .setProductId("premium_monthly")
                .setProductType(BillingClient.ProductType.SUBS)
                .build()
        )

        val params = QueryProductDetailsParams.newBuilder()
            .setProductList(productList)
            .build()

        billingClient.queryProductDetailsAsync(params) { billingResult, productDetailsList ->
            // Handle product details
        }
    }

    fun launchPurchaseFlow(productDetails: ProductDetails) {
        val flowParams = BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(
                listOf(
                    BillingFlowParams.ProductDetailsParams.newBuilder()
                        .setProductDetails(productDetails)
                        .build()
                )
            )
            .build()

        billingClient.launchBillingFlow(activity, flowParams)
    }
}

Advertising

Display Ads: Banner, interstitial, rewarded video Native Ads: Integrated content Sponsored Content: Premium placements

// Ad monetization with Google AdMob
class AdManager {
  constructor() {
    this.rewardedAd = null;
    this.interstitialAd = null;
  }

  async loadRewardedAd() {
    const { RewardedAd, RewardedAdEventType } = require('react-native-google-mobile-ads');

    this.rewardedAd = RewardedAd.createForAdRequest('ca-app-pub-xxxxx');

    this.rewardedAd.addAdEventListener(RewardedAdEventType.LOADED, () => {
      console.log('Rewarded ad loaded');
    });

    this.rewardedAd.addAdEventListener(RewardedAdEventType.EARNED_REWARD, reward => {
      this.grantReward(reward.amount, reward.type);
    });

    await this.rewardedAd.load();
  }

  async showRewardedAd(feature) {
    if (this.rewardedAd && this.rewardedAd.loaded) {
      await this.rewardedAd.show();
    } else {
      // Fallback: offer alternative or retry
      this.offerAlternativeToAd(feature);
    }
  }

  grantReward(amount, type) {
    // Grant user premium feature temporarily
    // or give them virtual currency
    console.log(`Granted ${amount} of ${type}`);
  }

  // Ad revenue tracking
  calculateARPDAU(dailyRevenue, dailyActiveUsers) {
    return dailyRevenue / dailyActiveUsers;
  }
}

Ad Revenue Optimization

  • ARPDAU (Average Revenue Per Daily Active User): Target $0.02-$0.10
  • Fill rate: Aim for 95%+
  • eCPM (effective cost per mille): Track by placement
  • Ad frequency capping: Max 3-5 per session

Enterprise Licensing

Best for: B2B SaaS, developer tools, infrastructure

// Enterprise license key management
interface EnterpriseLicense {
  organizationId: string;
  licenseKey: string;
  seats: number;
  features: string[];
  validUntil: Date;
  allowedDomains: string[];
  onPremiseDeployment: boolean;
  slaLevel: 'standard' | 'premium' | 'enterprise';
}

class LicenseValidator {
  private licenses: Map<string, EnterpriseLicense> = new Map();

  validateLicense(key: string, domain: string): {
    valid: boolean;
    license?: EnterpriseLicense;
    reason?: string;
  } {
    const license = this.licenses.get(key);

    if (!license) {
      return { valid: false, reason: 'Invalid license key' };
    }

    if (new Date() > license.validUntil) {
      return { valid: false, reason: 'License expired' };
    }

    if (!this.isDomainAllowed(domain, license.allowedDomains)) {
      return { valid: false, reason: 'Domain not authorized' };
    }

    const currentSeats = this.getActiveSeats(license.organizationId);
    if (currentSeats >= license.seats) {
      return { valid: false, reason: 'Seat limit exceeded' };
    }

    return { valid: true, license };
  }

  generateLicense(orgId: string, config: Partial<EnterpriseLicense>): string {
    const licenseKey = this.generateSecureKey();
    const license: EnterpriseLicense = {
      organizationId: orgId,
      licenseKey,
      seats: config.seats || 10,
      features: config.features || [],
      validUntil: config.validUntil || this.getOneYearFromNow(),
      allowedDomains: config.allowedDomains || [],
      onPremiseDeployment: config.onPremiseDeployment || false,
      slaLevel: config.slaLevel || 'standard',
    };

    this.licenses.set(licenseKey, license);
    return licenseKey;
  }

  private generateSecureKey(): string {
    const crypto = require('crypto');
    return crypto.randomBytes(32).toString('hex').toUpperCase();
  }

  private isDomainAllowed(domain: string, allowedDomains: string[]): boolean {
    if (allowedDomains.length === 0) return true;
    return allowedDomains.some(allowed =>
      domain.endsWith(allowed) || allowed === '*'
    );
  }
}

Marketplace/Commission Models

Best for: Platforms, two-sided markets

# Marketplace commission calculation
class MarketplaceRevenue:
    def __init__(self):
        self.commission_rates = {
            'standard': 0.15,  # 15% commission
            'premium': 0.10,   # 10% for verified sellers
            'enterprise': 0.05  # 5% for high-volume
        }
        self.payment_processing_fee = 0.029  # 2.9% + $0.30
        self.fixed_fee = 0.30

    def calculate_split(self, transaction_amount, seller_tier='standard'):
        """Calculate marketplace take and seller payout"""
        # Payment processing
        processing_cost = (transaction_amount * self.payment_processing_fee) + self.fixed_fee

        # Marketplace commission
        commission_rate = self.commission_rates[seller_tier]
        marketplace_commission = transaction_amount * commission_rate

        # Seller receives
        seller_payout = transaction_amount - marketplace_commission - processing_cost

        return {
            'transaction_amount': transaction_amount,
            'marketplace_commission': round(marketplace_commission, 2),
            'processing_cost': round(processing_cost, 2),
            'seller_payout': round(seller_payout, 2),
            'marketplace_net': round(marketplace_commission - processing_cost, 2),
            'commission_rate': commission_rate
        }

    def calculate_minimum_transaction(self, seller_tier='standard'):
        """Find minimum viable transaction to cover fees"""
        commission_rate = self.commission_rates[seller_tier]
        # Solve: amount * commission_rate > (amount * 0.029 + 0.30)
        min_amount = self.fixed_fee / (commission_rate - self.payment_processing_fee)
        return round(min_amount, 2)

# Example usage
marketplace = MarketplaceRevenue()
split = marketplace.calculate_split(100, 'standard')
# Result: Marketplace gets $15, Seller gets $81.80, Processing costs $3.20

Pricing Psychology

Anchoring

Place highest-priced tier first to make others seem reasonable.

<!-- Pricing page with anchoring -->
<div class="pricing-grid">
  <!-- Enterprise shown first as anchor -->
  <div class="pricing-card enterprise">
    <h3>Enterprise</h3>
    <div class="price">$999/mo</div>
    <span class="badge">Most Popular</span>
    <ul class="features">
      <li>Unlimited everything</li>
      <li>Dedicated support</li>
      <li>Custom integrations</li>
    </ul>
  </div>

  <!-- Pro seems reasonable by comparison -->
  <div class="pricing-card pro">
    <h3>Pro</h3>
    <div class="price">$99/mo</div>
    <span class="badge">Best Value</span>
    <ul class="features">
      <li>Advanced features</li>
      <li>Priority support</li>
      <li>API access</li>
    </ul>
  </div>

  <!-- Starter looks cheap -->
  <div class="pricing-card starter">
    <h3>Starter</h3>
    <div class="price">$19/mo</div>
    <ul class="features">
      <li>Basic features</li>
      <li>Email support</li>
    </ul>
  </div>
</div>

Decoy Pricing

Add a middle tier that makes the premium tier look better.

// Good-Better-Best pricing with decoy
const pricingTiers = [
  {
    name: 'Basic',
    price: 10,
    features: ['5 projects', 'Basic support'],
    valueScore: 5  // $2 per project
  },
  {
    name: 'Pro',  // DECOY - poor value
    price: 25,
    features: ['10 projects', 'Email support'],
    valueScore: 4,  // $2.50 per project
    isDecoy: true
  },
  {
    name: 'Premium',  // Looks great compared to Pro
    price: 30,
    features: ['Unlimited projects', 'Priority support', 'API access'],
    valueScore: 10,  // Much better value
    recommended: true
  }
];

Value Metric Selection

Choose metrics that grow with customer success:

Business Type Poor Value Metric Good Value Metric
Email marketing Number of templates Number of contacts
Analytics Number of dashboards Events tracked/month
Storage Number of folders GB stored
Team collaboration Features unlocked Number of seats
API service Number of endpoints API calls/month

Price Point Optimization

# A/B test price points
class PriceOptimizer:
    def __init__(self):
        self.test_results = []

    def analyze_price_point(self, price, conversions, visitors):
        """Analyze single price point performance"""
        conversion_rate = conversions / visitors
        revenue = price * conversions
        revenue_per_visitor = revenue / visitors

        return {
            'price': price,
            'conversion_rate': conversion_rate,
            'revenue': revenue,
            'rpv': revenue_per_visitor,  # Key metric
            'conversions': conversions
        }

    def find_optimal_price(self, test_data):
        """Find price with highest revenue per visitor"""
        results = []
        for test in test_data:
            result = self.analyze_price_point(
                test['price'],
                test['conversions'],
                test['visitors']
            )
            results.append(result)

        # Sort by revenue per visitor
        optimal = max(results, key=lambda x: x['rpv'])

        return {
            'optimal_price': optimal['price'],
            'expected_rpv': optimal['rpv'],
            'all_results': sorted(results, key=lambda x: x['rpv'], reverse=True)
        }

# Example: Test $9, $19, $29 price points
optimizer = PriceOptimizer()
test_data = [
    {'price': 9, 'conversions': 150, 'visitors': 1000},   # 15% CR, $1.35 RPV
    {'price': 19, 'conversions': 100, 'visitors': 1000},  # 10% CR, $1.90 RPV ✓ Best
    {'price': 29, 'conversions': 60, 'visitors': 1000},   # 6% CR, $1.74 RPV
]
optimal = optimizer.find_optimal_price(test_data)
# Result: $19 is optimal with $1.90 revenue per visitor

Implementation Patterns

Stripe Integration for Subscriptions

// Complete Stripe subscription flow
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const app = express();

// 1. Create checkout session
app.post('/create-checkout-session', async (req, res) => {
  const { priceId, customerId, successUrl, cancelUrl } = req.body;

  try {
    const session = await stripe.checkout.sessions.create({
      customer: customerId,
      mode: 'subscription',
      payment_method_types: ['card'],
      line_items: [{ price: priceId, quantity: 1 }],
      success_url: successUrl,
      cancel_url: cancelUrl,
      subscription_data: {
        trial_period_days: 14,
        metadata: {
          userId: req.user.id,
        },
      },
      allow_promotion_codes: true,
    });

    res.json({ sessionId: session.id });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// 2. Handle webhooks
app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;

  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  switch (event.type) {
    case 'checkout.session.completed':
      const session = event.data.object;
      await fulfillOrder(session);
      break;

    case 'customer.subscription.updated':
      const subscription = event.data.object;
      await updateUserSubscription(subscription);
      break;

    case 'customer.subscription.deleted':
      const canceledSub = event.data.object;
      await handleCancellation(canceledSub);
      break;

    case 'invoice.payment_failed':
      const failedInvoice = event.data.object;
      await handleFailedPayment(failedInvoice);
      break;
  }

  res.json({ received: true });
});

// 3. Create customer portal for self-service
app.post('/create-portal-session', async (req, res) => {
  const { customerId } = req.body;

  const session = await stripe.billingPortal.sessions.create({
    customer: customerId,
    return_url: 'https://yourapp.com/account',
  });

  res.json({ url: session.url });
});

// Helper functions
async function fulfillOrder(session) {
  const userId = session.metadata.userId;
  const subscriptionId = session.subscription;

  // Update database
  await db.users.update(userId, {
    stripeCustomerId: session.customer,
    subscriptionId: subscriptionId,
    subscriptionStatus: 'active',
    planName: session.metadata.planName,
  });

  // Send welcome email
  await sendEmail(userId, 'subscription_welcome');
}

Usage Tracking and Billing

# Usage tracking system for metered billing
from datetime import datetime, timedelta
from collections import defaultdict

class UsageTracker:
    def __init__(self, redis_client, stripe_client):
        self.redis = redis_client
        self.stripe = stripe_client

    def track_event(self, user_id, event_type, quantity=1, metadata=None):
        """Track a usage event"""
        timestamp = datetime.utcnow()

        # Store in Redis for fast access
        key = f"usage:{user_id}:{event_type}:{timestamp.strftime('%Y-%m')}"
        self.redis.hincrby(key, timestamp.strftime('%Y-%m-%d'), quantity)

        # Store detailed event
        event = {
            'user_id': user_id,
            'event_type': event_type,
            'quantity': quantity,
            'timestamp': timestamp.isoformat(),
            'metadata': metadata or {}
        }
        self.redis.lpush(f"events:{user_id}", json.dumps(event))

        # Report to Stripe for billing
        subscription_item_id = self.get_subscription_item_id(user_id, event_type)
        if subscription_item_id:
            self.report_to_stripe(subscription_item_id, quantity)

        # Check if approaching limit
        self.check_usage_alerts(user_id, event_type)

    def get_current_usage(self, user_id, event_type):
        """Get current month usage"""
        timestamp = datetime.utcnow()
        key = f"usage:{user_id}:{event_type}:{timestamp.strftime('%Y-%m')}"

        daily_usage = self.redis.hgetall(key)
        total = sum(int(v) for v in daily_usage.values())

        return {
            'total': total,
            'daily_breakdown': daily_usage,
            'period': timestamp.strftime('%Y-%m')
        }

    def report_to_stripe(self, subscription_item_id, quantity):
        """Report usage to Stripe for metered billing"""
        try:
            self.stripe.subscription_items.create_usage_record(
                subscription_item_id,
                quantity=quantity,
                timestamp=int(datetime.utcnow().timestamp()),
                action='increment'
            )
        except Exception as e:
            # Log error, implement retry logic
            print(f"Failed to report usage to Stripe: {e}")

    def check_usage_alerts(self, user_id, event_type):
        """Alert users approaching limits"""
        usage = self.get_current_usage(user_id, event_type)
        limit = self.get_user_limit(user_id, event_type)

        if not limit or limit == float('inf'):
            return

        percent_used = (usage['total'] / limit) * 100

        # Alert at 80%, 90%, 100%
        if percent_used >= 80 and not self.alert_sent(user_id, 80):
            self.send_usage_alert(user_id, event_type, percent_used, limit)

        if percent_used >= 100:
            self.enforce_limit(user_id, event_type)

License Key Management

// License key generation and validation (Go)
package licensing

import (
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "strings"
    "time"
)

type License struct {
    Key          string    `json:"key"`
    Email        string    `json:"email"`
    Product      string    `json:"product"`
    ValidUntil   time.Time `json:"valid_until"`
    MaxActivations int     `json:"max_activations"`
    Features     []string  `json:"features"`
}

type LicenseManager struct {
    secretKey string
}

func NewLicenseManager(secret string) *LicenseManager {
    return &LicenseManager{secretKey: secret}
}

// Generate creates a new license key
func (lm *LicenseManager) Generate(email, product string, duration time.Duration) string {
    expiry := time.Now().Add(duration).Unix()
    data := fmt.Sprintf("%s:%s:%d:%s", email, product, expiry, lm.secretKey)

    hash := sha256.Sum256([]byte(data))
    hashStr := hex.EncodeToString(hash[:])

    // Format as XXXX-XXXX-XXXX-XXXX
    key := strings.ToUpper(hashStr[:16])
    formatted := fmt.Sprintf("%s-%s-%s-%s",
        key[0:4], key[4:8], key[8:12], key[12:16])

    return formatted
}

// Validate checks if a license key is valid
func (lm *LicenseManager) Validate(key string, email string, product string) (bool, error) {
    // Remove hyphens
    cleanKey := strings.ReplaceAll(key, "-", "")

    // Check format
    if len(cleanKey) != 16 {
        return false, fmt.Errorf("invalid key format")
    }

    // Look up license in database
    license, err := lm.getLicenseFromDB(cleanKey)
    if err != nil {
        return false, err
    }

    // Verify email and product
    if license.Email != email || license.Product != product {
        return false, fmt.Errorf("license mismatch")
    }

    // Check expiration
    if time.Now().After(license.ValidUntil) {
        return false, fmt.Errorf("license expired")
    }

    // Check activation count
    activations := lm.getActivationCount(cleanKey)
    if activations >= license.MaxActivations {
        return false, fmt.Errorf("activation limit reached")
    }

    return true, nil
}

// Activate registers a device/machine with the license
func (lm *LicenseManager) Activate(key, deviceID string) error {
    // Record activation in database
    return lm.recordActivation(key, deviceID)
}

Trial Period Strategies

// Trial management system
interface TrialConfig {
  durationDays: number;
  requiresCreditCard: boolean;
  autoConvertToPaid: boolean;
  trialType: 'feature-limited' | 'time-limited' | 'hybrid';
}

class TrialManager {
  async startTrial(userId: string, config: TrialConfig): Promise<Trial> {
    const startDate = new Date();
    const endDate = new Date(startDate);
    endDate.setDate(endDate.getDate() + config.durationDays);

    const trial: Trial = {
      userId,
      startDate,
      endDate,
      status: 'active',
      requiresCreditCard: config.requiresCreditCard,
      autoConvertToPaid: config.autoConvertToPaid,
      daysRemaining: config.durationDays,
    };

    await this.saveTrial(trial);
    await this.scheduleTrialEndNotifications(trial);

    return trial;
  }

  async scheduleTrialEndNotifications(trial: Trial): Promise<void> {
    // Schedule emails: 7 days before, 3 days before, 1 day before, on expiry
    const notifications = [
      { daysBefore: 7, template: 'trial_ending_soon' },
      { daysBefore: 3, template: 'trial_ending_very_soon' },
      { daysBefore: 1, template: 'trial_ending_tomorrow' },
      { daysBefore: 0, template: 'trial_expired' },
    ];

    for (const notif of notifications) {
      const sendDate = new Date(trial.endDate);
      sendDate.setDate(sendDate.getDate() - notif.daysBefore);

      await this.scheduler.schedule({
        userId: trial.userId,
        template: notif.template,
        sendAt: sendDate,
        data: {
          daysRemaining: notif.daysBefore,
          upgradeUrl: this.generateUpgradeUrl(trial.userId),
        },
      });
    }
  }

  async checkTrialStatus(userId: string): Promise<TrialStatus> {
    const trial = await this.getTrial(userId);

    if (!trial) {
      return { hasTrialAccess: false, reason: 'no_trial' };
    }

    const now = new Date();
    const daysRemaining = Math.ceil(
      (trial.endDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)
    );

    if (daysRemaining <= 0) {
      if (trial.autoConvertToPaid && trial.requiresCreditCard) {
        await this.convertToSubscription(userId);
        return { hasTrialAccess: true, reason: 'converted_to_paid' };
      }

      return { hasTrialAccess: false, reason: 'trial_expired', daysRemaining: 0 };
    }

    return {
      hasTrialAccess: true,
      reason: 'trial_active',
      daysRemaining,
      showUpgradePrompt: daysRemaining <= 3,
    };
  }
}

Conversion Optimization

Paywall Placement

// Intelligent paywall timing
class PaywallStrategy {
  shouldShowPaywall(user: User): {
    show: boolean;
    reason: string;
    placement: string;
  } {
    // Don't show if already paid
    if (user.subscription.isPaid) {
      return { show: false, reason: 'already_subscribed', placement: 'none' };
    }

    // Show after value demonstration
    if (user.metrics.sessionsCount >= 3 && user.metrics.actionsCompleted >= 5) {
      return {
        show: true,
        reason: 'value_demonstrated',
        placement: 'post_action',
      };
    }

    // Show on premium feature access
    if (user.attemptedPremiumFeature) {
      return {
        show: true,
        reason: 'premium_feature_access',
        placement: 'feature_gate',
      };
    }

    // Show when hitting limit
    if (user.usage.current >= user.usage.limit * 0.8) {
      return {
        show: true,
        reason: 'approaching_limit',
        placement: 'usage_limit',
      };
    }

    return { show: false, reason: 'too_early', placement: 'none' };
  }

  getPaywallMessage(reason: string, user: User): string {
    const messages = {
      value_demonstrated: `You're loving ${APP_NAME}! Upgrade to unlock unlimited access.`,
      premium_feature_access: 'This feature is available on our Pro plan.',
      approaching_limit: `You've used ${user.usage.current} of ${user.usage.limit} ${user.usage.unit}. Upgrade for unlimited.`,
    };

    return messages[reason] || 'Upgrade to continue enjoying premium features.';
  }
}

Upgrade Prompts

// React upgrade prompt component
import React, { useState, useEffect } from 'react';

const UpgradePrompt = ({ trigger, user }) => {
  const [showPrompt, setShowPrompt] = useState(false);

  useEffect(() => {
    // Timing strategies
    const strategies = {
      immediate: () => true,
      delayed: () => setTimeout(() => setShowPrompt(true), 5000),
      onExit: () => {
        const handleExit = (e) => {
          if (e.clientY <= 0) setShowPrompt(true);
        };
        document.addEventListener('mouseleave', handleExit);
        return () => document.removeEventListener('mouseleave', handleExit);
      },
      afterValue: () => user.completedActions >= 3,
    };

    strategies[trigger.timing]?.();
  }, [trigger, user]);

  if (!showPrompt) return null;

  return (
    <div className="upgrade-prompt-overlay">
      <div className="upgrade-prompt-modal">
        <h2>{trigger.headline || 'Unlock Premium Features'}</h2>
        <p>{trigger.description}</p>

        <div className="pricing-comparison">
          <div className="current-plan">
            <h3>Free</h3>
            <ul>
              <li>✓ {user.usage.limit} {user.usage.unit}/month</li>
              <li>✗ Advanced analytics</li>
              <li>✗ Priority support</li>
            </ul>
          </div>

          <div className="upgrade-plan highlighted">
            <span className="badge">Popular</span>
            <h3>Pro</h3>
            <div className="price">$29/mo</div>
            <ul>
              <li>✓ Unlimited {user.usage.unit}</li>
              <li>✓ Advanced analytics</li>
              <li>✓ Priority support</li>
              <li>✓ Custom integrations</li>
            </ul>
            <button onClick={() => window.location.href = '/upgrade'}>
              Upgrade Now
            </button>
          </div>
        </div>

        <button className="dismiss" onClick={() => setShowPrompt(false)}>
          Maybe later
        </button>
      </div>
    </div>
  );
};

export default UpgradePrompt;

Feature Discovery

// Progressive feature disclosure
class FeatureOnboarding {
  constructor(userId) {
    this.userId = userId;
    this.features = [
      { id: 'basic_feature', tier: 'free', complexity: 1 },
      { id: 'advanced_analytics', tier: 'pro', complexity: 2 },
      { id: 'team_collaboration', tier: 'pro', complexity: 3 },
      { id: 'api_access', tier: 'enterprise', complexity: 4 },
    ];
  }

  async getNextFeatureToIntroduce() {
    const user = await this.getUser(this.userId);
    const completed = user.onboarding.completedSteps;

    // Find next feature user hasn't seen
    const nextFeature = this.features.find(
      (f) =>
        !completed.includes(f.id) &&
        f.complexity === completed.length + 1
    );

    if (!nextFeature) return null;

    // If premium feature, show upgrade opportunity
    if (nextFeature.tier !== 'free' && !user.subscription.isPaid) {
      return {
        ...nextFeature,
        locked: true,
        upgradeMessage: `This feature is available on our ${nextFeature.tier} plan.`,
      };
    }

    return nextFeature;
  }

  async recordFeatureUsage(featureId) {
    // Track which features users actually use
    await this.analytics.track(this.userId, 'feature_used', {
      feature_id: featureId,
      user_plan: await this.getUserPlan(this.userId),
      timestamp: new Date(),
    });
  }

  async identifyUpgradeOpportunities() {
    const usage = await this.getFeatureUsage(this.userId);

    // If user repeatedly tries premium features, show targeted upgrade
    const premiumAttempts = usage.filter(
      (u) => u.feature_tier !== 'free' && u.blocked
    );

    if (premiumAttempts.length >= 3) {
      return {
        shouldShowUpgrade: true,
        message: `You've tried to use premium features ${premiumAttempts.length} times. Upgrade to unlock them!`,
        features: [...new Set(premiumAttempts.map((p) => p.feature_id))],
      };
    }

    return { shouldShowUpgrade: false };
  }
}

Business Model Comparison

Model Selection Matrix

Factor Freemium Subscription Usage-Based One-Time Enterprise
Revenue predictability Medium High Medium Low High
Viral growth potential High Medium Low Medium Low
Customer LTV Medium High Variable Low Very High
Sales complexity Low Low Medium Low High
Support burden High Medium Low High Medium
Time to first revenue Slow Fast Fast Immediate Very Slow
Churn risk High Medium Low N/A Very Low
Best for B2C SaaS B2B SaaS APIs, Infrastructure Tools, Apps Enterprise Software

SaaS vs Marketplace

// Revenue model comparison
interface RevenueModel {
  type: 'saas' | 'marketplace';
  revenue: number;
  costs: number;
  margin: number;
}

function compareSaaSvsMarketplace(monthlyUsers: number): {
  saas: RevenueModel;
  marketplace: RevenueModel;
  recommendation: string;
} {
  // SaaS model: Subscription per user
  const saasPrice = 29;
  const saasConversion = 0.05; // 5% free to paid
  const saasCOGS = 5; // Per user cost

  const saasRevenue = monthlyUsers * saasConversion * saasPrice;
  const saasCosts = monthlyUsers * saasConversion * saasCOGS;
  const saasMargin = ((saasRevenue - saasCosts) / saasRevenue) * 100;

  // Marketplace model: Commission on transactions
  const avgTransactionValue = 100;
  const transactionsPerUser = 2;
  const commissionRate = 0.15; // 15%
  const paymentProcessing = 0.029;

  const marketplaceGMV = monthlyUsers * transactionsPerUser * avgTransactionValue;
  const marketplaceRevenue = marketplaceGMV * commissionRate;
  const marketplaceCosts = marketplaceGMV * paymentProcessing;
  const marketplaceMargin = ((marketplaceRevenue - marketplaceCosts) / marketplaceRevenue) * 100;

  const saasModel = {
    type: 'saas' as const,
    revenue: saasRevenue,
    costs: saasCosts,
    margin: saasMargin,
  };

  const marketplaceModel = {
    type: 'marketplace' as const,
    revenue: marketplaceRevenue,
    costs: marketplaceCosts,
    margin: marketplaceMargin,
  };

  const recommendation =
    marketplaceRevenue > saasRevenue
      ? 'Marketplace model generates more revenue with network effects'
      : 'SaaS model provides more predictable, scalable revenue';

  return {
    saas: saasModel,
    marketplace: marketplaceModel,
    recommendation,
  };
}

B2C vs B2B Pricing

# Pricing strategy by customer type
class PricingStrategy:
    def __init__(self, customer_type):
        self.customer_type = customer_type

        self.strategies = {
            'b2c': {
                'price_points': [9, 19, 49],  # Lower, single digit price sensitivity
                'billing_cycle': 'monthly',
                'trial_length': 7,
                'sales_process': 'self-serve',
                'payment_methods': ['card', 'paypal', 'apple_pay'],
                'decision_speed': 'fast',  # Minutes to hours
                'discount_strategy': 'volume',
            },
            'b2b_smb': {
                'price_points': [49, 99, 299],  # Mid-market
                'billing_cycle': 'annual',
                'trial_length': 14,
                'sales_process': 'low-touch',
                'payment_methods': ['card', 'invoice'],
                'decision_speed': 'medium',  # Days to weeks
                'discount_strategy': 'annual_commitment',
            },
            'b2b_enterprise': {
                'price_points': [999, 2999, 'custom'],  # High, often custom
                'billing_cycle': 'annual',
                'trial_length': 30,
                'sales_process': 'high-touch',
                'payment_methods': ['invoice', 'purchase_order'],
                'decision_speed': 'slow',  # Months
                'discount_strategy': 'negotiated',
            }
        }

    def get_pricing(self):
        return self.strategies[self.customer_type]

    def calculate_discount(self, base_price, seats, commitment_months):
        """Calculate appropriate discount based on customer type"""
        strategy = self.strategies[self.customer_type]

        if strategy['discount_strategy'] == 'volume':
            # B2C: Discount for prepayment
            if commitment_months >= 12:
                return base_price * 0.80  # 20% off annual
            return base_price

        elif strategy['discount_strategy'] == 'annual_commitment':
            # B2B SMB: Discount for annual + seats
            discount = 0
            if commitment_months >= 12:
                discount += 0.15
            if seats >= 10:
                discount += 0.05
            return base_price * (1 - discount)

        elif strategy['discount_strategy'] == 'negotiated':
            # Enterprise: Complex negotiation
            base_discount = 0.10  # Start at 10%
            if seats >= 100:
                base_discount += 0.10
            if commitment_months >= 24:
                base_discount += 0.05
            return base_price * (1 - min(base_discount, 0.30))  # Cap at 30%

Geographic Pricing

// Purchasing power parity (PPP) pricing
class GeographicPricing {
  constructor() {
    // PPP multipliers relative to USD
    this.pppMultipliers = {
      US: 1.0,
      GB: 0.95,
      CA: 0.85,
      AU: 0.90,
      DE: 0.90,
      FR: 0.88,
      IN: 0.25,
      BR: 0.40,
      MX: 0.45,
      PL: 0.55,
      AR: 0.35,
      ID: 0.30,
    };
  }

  calculateLocalPrice(baseUSDPrice, countryCode) {
    const multiplier = this.pppMultipliers[countryCode] || 1.0;
    const localPrice = baseUSDPrice * multiplier;

    // Round to local pricing conventions
    return this.roundToConvention(localPrice, countryCode);
  }

  roundToConvention(price, countryCode) {
    // Different regions have different "charm pricing" conventions
    const conventions = {
      US: (p) => Math.round(p) - 0.01, // $9.99
      GB: (p) => Math.round(p) - 0.01, // £9.99
      EU: (p) => Math.round(p), // €10
      IN: (p) => Math.round(p / 10) * 10 - 1, // ₹99
      BR: (p) => Math.round(p / 10) * 10 - 0.01, // R$99.99
    };

    const region = this.getRegion(countryCode);
    const convention = conventions[region] || ((p) => Math.round(p));

    return convention(price);
  }

  shouldShowLocalPricing(countryCode) {
    // Only show local pricing if significantly different
    const multiplier = this.pppMultipliers[countryCode] || 1.0;
    return multiplier < 0.75; // 25%+ difference
  }

  getRegion(countryCode) {
    const regions = {
      US: ['US', 'CA'],
      GB: ['GB'],
      EU: ['DE', 'FR', 'ES', 'IT', 'PL'],
      IN: ['IN'],
      BR: ['BR', 'AR', 'MX'],
    };

    for (const [region, countries] of Object.entries(regions)) {
      if (countries.includes(countryCode)) return region;
    }

    return 'US';
  }
}

// Example usage
const pricing = new GeographicPricing();
const basePrice = 29; // USD

console.log('US:', pricing.calculateLocalPrice(basePrice, 'US')); // $28.99
console.log('IN:', pricing.calculateLocalPrice(basePrice, 'IN')); // ₹199 (~$7.25)
console.log('BR:', pricing.calculateLocalPrice(basePrice, 'BR')); // R$49.99 (~$11.60)

Anti-Patterns

Over-Complicating Pricing

Bad: 6+ tiers with confusing feature matrices Good: 3 clear tiers with obvious value differences

// BAD: Too many tiers
const badPricing = [
  { name: 'Free', price: 0 },
  { name: 'Starter', price: 9 },
  { name: 'Basic', price: 19 },
  { name: 'Pro', price: 29 },
  { name: 'Pro Plus', price: 49 },
  { name: 'Business', price: 99 },
  { name: 'Enterprise', price: 299 },
];

// GOOD: Clear progression
const goodPricing = [
  { name: 'Free', price: 0, target: 'Individuals', features: ['Basic'] },
  { name: 'Pro', price: 29, target: 'Power users', features: ['Advanced'] },
  { name: 'Team', price: 99, target: 'Teams', features: ['Collaboration'] },
];

Charging Too Early

Anti-pattern: Paywall before demonstrating value

// BAD: Immediate paywall
app.get('/signup', (req, res) => {
  res.redirect('/pricing'); // No value shown
});

// GOOD: Value-first approach
app.get('/signup', async (req, res) => {
  await createFreeAccount(req.user);
  await grantTrialAccess(req.user, 14);
  res.redirect('/onboarding'); // Show value first
});

Ignoring Upgrade Friction

Anti-pattern: Making it hard to upgrade or downgrade

# BAD: Requires contacting sales to upgrade
def upgrade_plan(user_id, new_plan):
    return {"message": "Please contact sales@company.com to upgrade"}

# GOOD: Self-service upgrade flow
def upgrade_plan(user_id, new_plan):
    user = get_user(user_id)
    price_difference = calculate_prorated_upgrade(user, new_plan)

    return {
        "can_upgrade": True,
        "new_plan": new_plan,
        "charge_today": price_difference,
        "next_billing_date": user.next_billing_date,
        "upgrade_url": f"/checkout?plan={new_plan}"
    }

Poor Trial Design

Anti-patterns:

  • Too short (< 7 days)
  • Requires credit card with no warning
  • Full feature access = no upgrade urgency
  • No communication during trial
// GOOD trial design
const trialConfig = {
  duration: 14, // Long enough to see value
  requiresCreditCard: false, // Reduce friction
  limitations: 'usage', // Create upgrade urgency
  communications: [
    { day: 0, type: 'welcome', goal: 'onboard' },
    { day: 3, type: 'tips', goal: 'engagement' },
    { day: 7, type: 'milestone', goal: 'retention' },
    { day: 11, type: 'upgrade_offer', goal: 'conversion' },
    { day: 13, type: 'final_reminder', goal: 'conversion' },
  ],
};

Not Measuring Conversion

Anti-pattern: No data on pricing performance

# Track conversion metrics
class PricingAnalytics:
    def track_conversion_funnel(self, user_id, step):
        """Track each step of conversion funnel"""
        funnel_steps = [
            'viewed_pricing',
            'clicked_plan',
            'entered_payment',
            'completed_purchase'
        ]

        self.analytics.track(user_id, step, {
            'timestamp': datetime.utcnow(),
            'funnel_position': funnel_steps.index(step),
            'session_id': self.get_session_id()
        })

    def calculate_conversion_rate(self, from_step, to_step, days=30):
        """Calculate conversion rate between funnel steps"""
        users_at_start = self.get_users_at_step(from_step, days)
        users_at_end = self.get_users_at_step(to_step, days)

        return {
            'conversion_rate': len(users_at_end) / len(users_at_start),
            'from_step': from_step,
            'to_step': to_step,
            'period_days': days
        }

Examples

Example 1: SaaS Freemium with Stripe

// Complete freemium SaaS implementation
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

// Define pricing tiers
const PLANS = {
  free: {
    name: 'Free',
    price: 0,
    stripePriceId: null,
    limits: { projects: 3, storage: 1024, apiCalls: 1000 },
  },
  pro: {
    name: 'Pro',
    price: 29,
    stripePriceId: 'price_xxxxx',
    limits: { projects: 50, storage: 10240, apiCalls: 50000 },
  },
  team: {
    name: 'Team',
    price: 99,
    stripePriceId: 'price_yyyyy',
    limits: { projects: 200, storage: 102400, apiCalls: 500000 },
  },
};

// Middleware to check plan access
function requiresPlan(minPlan) {
  return async (req, res, next) => {
    const user = await getUser(req.userId);
    const planHierarchy = ['free', 'pro', 'team'];

    if (planHierarchy.indexOf(user.plan) >= planHierarchy.indexOf(minPlan)) {
      next();
    } else {
      res.status(403).json({
        error: 'Upgrade required',
        current_plan: user.plan,
        required_plan: minPlan,
        upgrade_url: '/upgrade',
      });
    }
  };
}

// Create subscription
app.post('/api/subscribe', async (req, res) => {
  const { planId } = req.body;
  const plan = PLANS[planId];

  if (!plan || plan.price === 0) {
    return res.status(400).json({ error: 'Invalid plan' });
  }

  try {
    // Create or get Stripe customer
    let customerId = req.user.stripeCustomerId;
    if (!customerId) {
      const customer = await stripe.customers.create({
        email: req.user.email,
        metadata: { userId: req.user.id },
      });
      customerId = customer.id;
      await updateUser(req.user.id, { stripeCustomerId: customerId });
    }

    // Create checkout session
    const session = await stripe.checkout.sessions.create({
      customer: customerId,
      mode: 'subscription',
      line_items: [{ price: plan.stripePriceId, quantity: 1 }],
      success_url: `${process.env.APP_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
      cancel_url: `${process.env.APP_URL}/pricing`,
      subscription_data: {
        trial_period_days: 14,
        metadata: { userId: req.user.id, plan: planId },
      },
    });

    res.json({ checkoutUrl: session.url });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Protected route example
app.post('/api/projects', requiresPlan('pro'), async (req, res) => {
  // Only Pro and Team users can access this
  const project = await createProject(req.user.id, req.body);
  res.json(project);
});

Example 2: Usage-Based API Pricing

# API with usage-based metered billing
from flask import Flask, request, jsonify
import stripe
import redis
from datetime import datetime

app = Flask(__name__)
stripe.api_key = os.getenv('STRIPE_SECRET_KEY')
redis_client = redis.Redis(host='localhost', port=6379, db=0)

# Pricing tiers
PRICING = {
    'pay_as_you_go': {
        'base': 0,
        'per_request': 0.001,
        'included_requests': 0
    },
    'startup': {
        'base': 29,
        'per_request': 0.0005,
        'included_requests': 10000
    },
    'growth': {
        'base': 99,
        'per_request': 0.0002,
        'included_requests': 100000
    }
}

def track_api_usage(user_id, endpoint, response_time):
    """Track API usage for billing"""
    timestamp = datetime.utcnow()
    month_key = timestamp.strftime('%Y-%m')

    # Increment usage counter
    redis_client.hincrby(f'usage:{user_id}:{month_key}', 'requests', 1)
    redis_client.hincrby(f'usage:{user_id}:{month_key}', 'total_time_ms', response_time)

    # Log individual request
    redis_client.lpush(f'requests:{user_id}:{month_key}', json.dumps({
        'endpoint': endpoint,
        'timestamp': timestamp.isoformat(),
        'response_time': response_time
    }))

    # Report to Stripe for metered billing
    subscription_item_id = get_subscription_item_id(user_id)
    if subscription_item_id:
        try:
            stripe.subscription_items.create_usage_record(
                subscription_item_id,
                quantity=1,
                timestamp=int(timestamp.timestamp())
            )
        except Exception as e:
            print(f"Failed to report usage: {e}")

@app.route('/api/v1/<path:endpoint>', methods=['GET', 'POST'])
def api_endpoint(endpoint):
    # Authenticate
    api_key = request.headers.get('X-API-Key')
    user = authenticate_api_key(api_key)

    if not user:
        return jsonify({'error': 'Invalid API key'}), 401

    # Check rate limits
    usage = get_current_usage(user['id'])
    plan = PRICING[user['plan']]

    billable_requests = max(0, usage['requests'] - plan['included_requests'])
    estimated_cost = plan['base'] + (billable_requests * plan['per_request'])

    # Track usage
    start_time = datetime.utcnow()
    result = process_api_request(endpoint, request)
    response_time = (datetime.utcnow() - start_time).total_seconds() * 1000

    track_api_usage(user['id'], endpoint, response_time)

    # Add usage headers
    response = jsonify(result)
    response.headers['X-RateLimit-Remaining'] = plan['included_requests'] - usage['requests']
    response.headers['X-Usage-Month'] = usage['requests']
    response.headers['X-Estimated-Cost'] = f"${estimated_cost:.2f}"

    return response

@app.route('/api/usage', methods=['GET'])
def get_usage():
    """Get current month usage and costs"""
    api_key = request.headers.get('X-API-Key')
    user = authenticate_api_key(api_key)

    usage = get_current_usage(user['id'])
    plan = PRICING[user['plan']]

    billable = max(0, usage['requests'] - plan['included_requests'])
    cost = plan['base'] + (billable * plan['per_request'])

    return jsonify({
        'period': datetime.utcnow().strftime('%Y-%m'),
        'plan': user['plan'],
        'requests': {
            'total': usage['requests'],
            'included': plan['included_requests'],
            'billable': billable
        },
        'cost': {
            'base': plan['base'],
            'usage': billable * plan['per_request'],
            'total': cost
        }
    })

Example 3: Mobile App with IAP

// iOS app with in-app purchases and subscriptions
import StoreKit
import SwiftUI

// Product IDs
enum ProductID: String, CaseIterable {
    case proMonthly = "com.app.pro.monthly"
    case proYearly = "com.app.pro.yearly"
    case premiumUnlock = "com.app.premium.unlock"
    case creditsPack = "com.app.credits.100"
}

@MainActor
class StoreManager: ObservableObject {
    @Published var products: [Product] = []
    @Published var purchasedProductIDs = Set<String>()
    @Published var subscriptionStatus: SubscriptionStatus?

    private var updateListenerTask: Task<Void, Error>?

    init() {
        updateListenerTask = listenForTransactions()

        Task {
            await loadProducts()
            await updatePurchasedProducts()
        }
    }

    deinit {
        updateListenerTask?.cancel()
    }

    func listenForTransactions() -> Task<Void, Error> {
        return Task.detached {
            for await result in Transaction.updates {
                do {
                    let transaction = try self.checkVerified(result)
                    await self.updatePurchasedProducts()
                    await transaction.finish()
                } catch {
                    print("Transaction verification failed: \(error)")
                }
            }
        }
    }

    func loadProducts() async {
        do {
            let productIDs = ProductID.allCases.map { $0.rawValue }
            self.products = try await Product.products(for: productIDs)
        } catch {
            print("Failed to load products: \(error)")
        }
    }

    func purchase(_ product: Product) async throws -> Transaction? {
        let result = try await product.purchase()

        switch result {
        case .success(let verification):
            let transaction = try checkVerified(verification)
            await updatePurchasedProducts()
            await transaction.finish()
            return transaction

        case .userCancelled, .pending:
            return nil

        @unknown default:
            return nil
        }
    }

    func updatePurchasedProducts() async {
        var purchasedIDs = Set<String>()

        for await result in Transaction.currentEntitlements {
            guard case .verified(let transaction) = result else { continue }

            if transaction.revocationDate == nil {
                purchasedIDs.insert(transaction.productID)
            }
        }

        self.purchasedProductIDs = purchasedIDs

        // Check subscription status
        await updateSubscriptionStatus()
    }

    func updateSubscriptionStatus() async {
        // Check if user has active subscription
        let hasProMonthly = purchasedProductIDs.contains(ProductID.proMonthly.rawValue)
        let hasProYearly = purchasedProductIDs.contains(ProductID.proYearly.rawValue)

        if hasProMonthly || hasProYearly {
            subscriptionStatus = .active
        } else {
            subscriptionStatus = .inactive
        }
    }

    func checkVerified<T>(_ result: VerificationResult<T>) throws -> T {
        switch result {
        case .unverified:
            throw StoreError.failedVerification
        case .verified(let safe):
            return safe
        }
    }

    func hasAccess(to feature: String) -> Bool {
        // Check if user has purchased access
        switch feature {
        case "premium":
            return subscriptionStatus == .active ||
                   purchasedProductIDs.contains(ProductID.premiumUnlock.rawValue)
        default:
            return false
        }
    }
}

// Pricing view
struct PricingView: View {
    @StateObject private var store = StoreManager()
    @State private var isPurchasing = false

    var body: some View {
        VStack(spacing: 20) {
            Text("Unlock Premium Features")
                .font(.title)
                .fontWeight(.bold)

            ForEach(store.products, id: \.id) { product in
                PricingCard(product: product) {
                    await purchaseProduct(product)
                }
            }

            Button("Restore Purchases") {
                Task {
                    try? await AppStore.sync()
                }
            }
        }
        .padding()
    }

    func purchaseProduct(_ product: Product) async {
        isPurchasing = true

        do {
            if let transaction = try await store.purchase(product) {
                // Purchase successful
                print("Purchased: \(transaction.productID)")
            }
        } catch {
            print("Purchase failed: \(error)")
        }

        isPurchasing = false
    }
}

enum SubscriptionStatus {
    case active
    case inactive
    case grace
    case trial
}

enum StoreError: Error {
    case failedVerification
}

Example 4: Dynamic Pricing with A/B Testing

// A/B testing framework for pricing
interface PricingExperiment {
  id: string;
  name: string;
  variants: PricingVariant[];
  status: 'draft' | 'running' | 'completed';
  startDate: Date;
  endDate?: Date;
  targetMetric: 'revenue' | 'conversion' | 'ltv';
}

interface PricingVariant {
  id: string;
  name: string;
  price: number;
  allocation: number; // Percentage of traffic
  conversions: number;
  revenue: number;
  visitors: number;
}

class PricingExperimentManager {
  async assignVariant(userId: string, experimentId: string): Promise<PricingVariant> {
    // Check if user already assigned
    const existing = await this.getAssignment(userId, experimentId);
    if (existing) return existing;

    // Get experiment
    const experiment = await this.getExperiment(experimentId);
    if (experiment.status !== 'running') {
      return experiment.variants[0]; // Default to control
    }

    // Assign based on allocation percentages
    const rand = this.hash(userId + experimentId) % 100;
    let cumulative = 0;

    for (const variant of experiment.variants) {
      cumulative += variant.allocation;
      if (rand < cumulative) {
        await this.saveAssignment(userId, experimentId, variant.id);
        return variant;
      }
    }

    return experiment.variants[0];
  }

  async trackConversion(
    userId: string,
    experimentId: string,
    revenue: number
  ): Promise<void> {
    const assignment = await this.getAssignment(userId, experimentId);
    if (!assignment) return;

    await this.incrementMetrics(experimentId, assignment.variantId, {
      conversions: 1,
      revenue,
    });
  }

  async analyzeExperiment(experimentId: string): Promise<ExperimentResults> {
    const experiment = await this.getExperiment(experimentId);
    const control = experiment.variants[0];
    const results: VariantResult[] = [];

    for (const variant of experiment.variants) {
      const conversionRate = variant.conversions / variant.visitors;
      const avgRevenue = variant.revenue / variant.visitors;

      // Statistical significance test
      const significance = this.calculateSignificance(
        variant,
        control,
        experiment.targetMetric
      );

      results.push({
        variantId: variant.id,
        name: variant.name,
        conversionRate,
        avgRevenue,
        totalRevenue: variant.revenue,
        visitors: variant.visitors,
        improvement: ((avgRevenue - control.revenue / control.visitors) /
          (control.revenue / control.visitors)) * 100,
        isSignificant: significance.pValue < 0.05,
        confidence: significance.confidence,
      });
    }

    return {
      experimentId,
      results: results.sort((a, b) => b.avgRevenue - a.avgRevenue),
      winner: results.find((r) => r.isSignificant && r.improvement > 0),
      recommendation: this.generateRecommendation(results),
    };
  }

  private calculateSignificance(
    variant: PricingVariant,
    control: PricingVariant,
    metric: string
  ): { pValue: number; confidence: number } {
    // Simplified z-test for proportions
    const p1 = variant.conversions / variant.visitors;
    const p2 = control.conversions / control.visitors;
    const n1 = variant.visitors;
    const n2 = control.visitors;

    const pooled = (variant.conversions + control.conversions) / (n1 + n2);
    const se = Math.sqrt(pooled * (1 - pooled) * (1 / n1 + 1 / n2));
    const z = (p1 - p2) / se;

    // Approximate p-value
    const pValue = 2 * (1 - this.normalCDF(Math.abs(z)));
    const confidence = (1 - pValue) * 100;

    return { pValue, confidence };
  }

  private normalCDF(z: number): number {
    // Approximation of cumulative distribution function
    const t = 1 / (1 + 0.2316419 * Math.abs(z));
    const d = 0.3989423 * Math.exp((-z * z) / 2);
    const probability =
      d *
      t *
      (0.3193815 +
        t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));

    return z > 0 ? 1 - probability : probability;
  }

  private hash(str: string): number {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i);
      hash = (hash << 5) - hash + char;
      hash = hash & hash;
    }
    return Math.abs(hash);
  }
}

// Usage example
const experimentManager = new PricingExperimentManager();

// Create experiment
const experiment: PricingExperiment = {
  id: 'pricing_test_001',
  name: 'Pro Plan Price Point Test',
  variants: [
    { id: 'control', name: 'Control $29', price: 29, allocation: 34, conversions: 0, revenue: 0, visitors: 0 },
    { id: 'variant_a', name: 'Test $19', price: 19, allocation: 33, conversions: 0, revenue: 0, visitors: 0 },
    { id: 'variant_b', name: 'Test $39', price: 39, allocation: 33, conversions: 0, revenue: 0, visitors: 0 },
  ],
  status: 'running',
  startDate: new Date(),
  targetMetric: 'revenue',
};

// In pricing page
app.get('/pricing', async (req, res) => {
  const variant = await experimentManager.assignVariant(req.user.id, 'pricing_test_001');

  res.render('pricing', {
    price: variant.price,
    experimentId: 'pricing_test_001',
  });
});

// Track conversion
app.post('/subscribe', async (req, res) => {
  // Process subscription
  const subscription = await createSubscription(req.user.id, req.body.planId);

  // Track experiment conversion
  await experimentManager.trackConversion(
    req.user.id,
    'pricing_test_001',
    subscription.amount
  );

  res.json({ success: true });
});

Key Takeaways for 6-Day Sprints:

  1. Day 1: Choose model based on value delivery pattern
  2. Day 2: Implement basic payment flow (Stripe Checkout is fastest)
  3. Day 3: Add feature gates and usage tracking
  4. Day 4: Create pricing page with 3 clear tiers
  5. Day 5: Implement trial and upgrade flows
  6. Day 6: Add analytics tracking and test end-to-end

Critical Decisions:

  • Freemium vs paid-only: Freemium if viral growth matters
  • Monthly vs annual: Offer both, 20% discount on annual
  • Trial length: 14 days is optimal for most B2B SaaS
  • Payment provider: Stripe for speed, flexibility, and developer experience

Revenue Model Priority: Subscription > Usage-based > One-time > Ads (for predictability and LTV)