
Pricing Validation
- 170 installs
- 145 repo stars
- Updated April 2, 2026
- guia-matthieu/clawfu-skills
Test price points, packaging, and willingness-to-pay with structured interviews and experiments before locking billing, contracts, or storefront pricing.
About
Runs structured pricing validation—interview scripts, tier comparisons, anchoring tests, and segment sensitivity checks—so teams set packages and price points grounded in buyer behavior instead of guesses.
- Willingness-to-pay interview scripts
- Tier and packaging comparison tests
- Anchoring and decoy design patterns
- Segments price sensitivity analysis
- Go/no-go thresholds before launch
Pricing Validation by the numbers
- 170 all-time installs (skills.sh)
- Ranked #357 of 853 Sales & Marketing skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/guia-matthieu/clawfu-skills --skill pricing-validationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 170 |
|---|---|
| repo stars | ★ 145 |
| Last updated | April 2, 2026 |
| Repository | guia-matthieu/clawfu-skills ↗ |
What it does
Test price points, packaging, and willingness-to-pay with structured interviews and experiments before locking billing, contracts, or storefront pricing.
Files
Pricing Validation
Test willingness to pay before launching with proven pricing research methodologies. Combine Van Westendorp, Gabor-Granger, and behavioral techniques to find your optimal price point.
When to Use This Skill
- After solution validation to test willingness to pay
- Before launch to set initial pricing
- Pricing changes to test new price points
- New segments to understand price sensitivity by segment
- Competitive positioning to price against alternatives
- Feature pricing to understand value of add-ons
Methodology Foundation
| Aspect | Details |
|---|---|
| Source | Van Westendorp PSM (1976), Gabor-Granger method, behavioral economics |
| Core Principle | "People can't accurately predict what they'd pay. Use structured methods to triangulate, and verify with real purchasing behavior." |
| Why This Matters | Pricing wrong costs you customers (too high) or money (too low). Every 1% improvement in price has 11% profit impact on average. |
What Claude Does vs What You Decide
| Claude Does | You Decide |
|---|---|
| Structures analysis frameworks | Strategic priorities |
| Synthesizes market data | Competitive positioning |
| Identifies opportunities | Resource allocation |
| Creates strategic options | Final strategy selection |
| Suggests implementation approaches | Execution decisions |
What This Skill Does
1. Finds price range - Identifies acceptable pricing boundaries 2. Tests price points - Measures demand at specific prices 3. Identifies optimal price - Balances revenue and conversion 4. Segments by willingness - Who will pay more vs. less 5. Validates pricing model - Subscription vs. one-time vs. usage 6. Reveals value perceptions - What drives pricing acceptance
How to Use
Run Van Westendorp Analysis
I want to find the optimal price range for [product].
Run me through Van Westendorp Price Sensitivity Meter.
Provide the questions and analysis framework.Test Specific Price Points
I'm considering pricing at [$X, $Y, $Z].
Help me design a Gabor-Granger test to measure demand at each price.Validate Pricing Without Asking Directly
I want to validate my $99/month pricing without asking "would you pay?"
What behavioral and indirect methods can I use?Instructions
Step 1: Choose Your Pricing Research Method
## Pricing Research Methods
### Method Selection Guide
| Method | Best For | Sample Size | Complexity |
|--------|----------|-------------|------------|
| Van Westendorp PSM | Finding price range | 100-200+ | Medium |
| Gabor-Granger | Testing specific prices | 50-100 | Low |
| Conjoint Analysis | Feature/price trade-offs | 200+ | High |
| A/B Testing | Final validation | 500+ visitors | Medium |
| Behavioral Signals | Qualitative insights | 10-30 | Low |
### When to Use Each
**Van Westendorp (Price Sensitivity Meter):**
- You don't know where to start
- Want to find acceptable price range
- Have access to survey respondents
**Gabor-Granger:**
- You have candidate price points
- Want to test specific prices
- Need demand curve
**Conjoint Analysis:**
- Multiple features and price levels
- Need to understand trade-offs
- Have resources for complex analysis
**A/B Testing:**
- Already have traffic/users
- Testing final price decisions
- Want real conversion data
**Behavioral Signals:**
- Early stage, small sample
- Qualitative validation
- Can't run formal surveys---
Step 2: Van Westendorp Price Sensitivity Meter
## Van Westendorp PSM
### The Four Questions
Ask respondents all four questions about the product:
1. **TOO EXPENSIVE:**
"At what price would you consider this product to be so expensive
that you would not consider buying it?"
2. **TOO CHEAP:**
"At what price would you consider this product to be priced so low
that you would question its quality?"
3. **EXPENSIVE BUT WORTH IT:**
"At what price would you consider this product starting to get expensive—
it's not out of the question, but you'd have to think about buying it?"
4. **GOOD VALUE:**
"At what price would you consider this product to be a bargain—
a great buy for the money?"
### Analysis
Plot cumulative distribution curves for each response:
- "Too Expensive" (cumulative from low to high)
- "Too Cheap" (cumulative from high to low)
- "Expensive" (cumulative from low to high)
- "Good Value" (cumulative from high to low)
### Key Price Points
| Point | Definition | Meaning |
|-------|------------|---------|
| **PMC** (Point of Marginal Cheapness) | Where "Too Cheap" intersects "Expensive" | Below this, quality concerns emerge |
| **PME** (Point of Marginal Expensiveness) | Where "Too Expensive" intersects "Good Value" | Above this, significant resistance |
| **OPP** (Optimal Price Point) | Where "Too Expensive" intersects "Too Cheap" | Best price for adoption |
| **IDP** (Indifference Price Point) | Where "Expensive" intersects "Good Value" | What people expect to pay |
### Acceptable Price Range
PMC to PME = your acceptable pricing range
### Interpretation Guide
**Narrow range (PMC close to PME):**
- Price sensitive market
- Commodity perceptions
- Strong competitor reference prices
**Wide range (PMC far from PME):**
- Price flexibility
- Differentiated product
- Segmentation opportunity---
Step 3: Gabor-Granger Method
## Gabor-Granger Price Testing
### How It Works
Show product, then ask purchase intent at specific price points.
Start high or low, adjust based on response.
### Question Format
**Monadic (one price per person):**
Show each respondent only ONE price:
"Would you buy this product at $X?"
- Definitely would buy
- Probably would buy
- Might or might not buy
- Probably would not buy
- Definitely would not buy
**Sequential (multiple prices per person):**
If "Yes" → show higher price
If "No" → show lower price
Continue until you find their threshold
### Analysis
**Purchase Intent Translation:**
| Response | Probability |
|----------|-------------|
| Definitely | 90% |
| Probably | 70% |
| Might | 30% |
| Probably not | 10% |
| Definitely not | 0% |
**Demand Curve:**
| Price | Purchase Intent | Weighted % | Expected Revenue |
|-------|-----------------|------------|------------------|
| $49 | 80% | 68% | $49 × 68% = $33.32 |
| $79 | 60% | 48% | $79 × 48% = $37.92 |
| $99 | 40% | 32% | $99 × 32% = $31.68 |
| $149 | 20% | 14% | $149 × 14% = $20.86 |
**Optimal Price:** $79 (highest expected revenue)
### Sample Size Requirements
- 30-50 per price point (monadic)
- 50-100 total (sequential)
- Segment analysis requires more---
Step 4: Behavioral/Indirect Methods
## Pricing Validation Without Asking About Price
### Why Indirect Methods Matter
- People overestimate willingness to pay when hypothetical
- Real behavior differs from stated intent
- Indirect signals often more reliable
### Method 1: Reference Price Anchoring
**Questions to ask:**
- "What are you currently spending on [similar product/solution]?"
- "What's the most you've ever paid for [category]?"
- "What would you expect this to cost based on similar products?"
**Analysis:**
If they're spending $100/month on alternatives, $150 might be possible.
If they've never paid >$50 for similar, $200 is risky.
### Method 2: Value Quantification
**Questions to ask:**
- "How much time does this problem cost you per week?"
- "What's the cost of this problem not being solved?"
- "If this saved you X hours/week, what's that worth?"
**Analysis:**
If problem costs them $500/month in time, $100/month solution seems cheap.
Price relative to quantified value, not arbitrary numbers.
### Method 3: Trade-off Questions
**Instead of:** "Would you pay $X?"
**Ask:** "Which would you choose?"
- Option A: $79/month with features X, Y, Z
- Option B: $49/month with features X, Y only
- Option C: Free with feature X only
**Analysis:**
Distribution reveals price sensitivity and feature value.
### Method 4: Commitment Testing
**Real commitment signals:**
- "Would you put $50 down as a deposit for early access?"
- "Would you sign a letter of intent at $X?"
- "Would you pay for a paid pilot at $X/month?"
**Analysis:**
Real money > stated intent.
Even small commitment = strong signal.
### Method 5: Negotiation Simulation
**Questions to ask:**
- "If this was $X, would you push back? At what price would you push back?"
- "What price would make this an easy decision?"
- "What price would require significant justification internally?"
**Analysis:**
- "Easy decision" price = conservative but low-friction
- "Push back" price = ceiling---
Step 5: Analyze and Decide
## Pricing Analysis Framework
### Data Synthesis
| Method | Finding | Confidence |
|--------|---------|------------|
| Van Westendorp | Range: $X - $Y, OPP: $Z | High/Med/Low |
| Gabor-Granger | Optimal: $X | High/Med/Low |
| Reference prices | Currently paying $X | High/Med/Low |
| Value quantification | Problem worth $X/month | High/Med/Low |
| Commitments | X people committed at $Y | High/Med/Low |
### Triangulation
**Look for convergence:**
- If Van Westendorp OPP = $89
- And Gabor-Granger optimal = $79
- And reference prices = $50-100
→ Price in $79-99 range is validated
**Red flags:**
- Wide divergence between methods
- Reference prices far below target
- No commitments at target price
### Price Setting Decision
| Factor | Weight | Your Finding | Score |
|--------|--------|--------------|-------|
| Research-based optimal | 30% | | |
| Competitive positioning | 25% | | |
| Value quantification | 25% | | |
| Commitment signals | 20% | | |
### Pricing Model Validation
Also validate the MODEL, not just the price:
- Subscription vs. one-time
- Per user vs. flat rate
- Monthly vs. annual
- Usage-based vs. fixed
**Questions to test model:**
- "How do you typically pay for software like this?"
- "Would you prefer monthly or annual billing?"
- "Does per-user pricing make sense for your team?"
### Risk Assessment
| Price Point | Upside | Downside | Risk Level |
|-------------|--------|----------|------------|
| $79 (low) | Faster adoption | Leave money on table | Low |
| $99 (mid) | Balanced | May need to discount | Medium |
| $129 (high) | Max revenue | Slower adoption | High |
**Recommendation format:**
"Launch at $[X] based on [evidence]. Plan to test $[Y] with segment [Z] within 90 days."---
Examples
Example 1: SaaS Pricing Validation
Input:
"I'm launching a project management tool for marketing teams. I'm thinking $49/user/month. How do I validate this?"
Output:
Pricing Validation Plan: Marketing PM Tool
Multi-Method Approach
Step 1: Reference Price Research
In customer interviews, ask:
- "What are you paying for project management today?"
- "What's your total spend on marketing tools?"
- "What's the most expensive per-seat tool you use?"
Common findings in this space:
- Asana: $10-30/user
- Monday: $8-24/user
- Notion: $10-15/user
Initial insight: $49/user is 2-3x competitors. Need strong differentiation story.
Step 2: Van Westendorp Survey
Survey 100+ target customers:
"Imagine a project management tool designed specifically for marketing teams with campaign calendars, creative workflows, and ROI tracking."
1. At what price per user/month would you consider this too expensive? 2. At what price per user/month would you question the quality? 3. At what price per user/month does this become expensive but still worth considering? 4. At what price per user/month would this be a great value?
Step 3: Value Quantification
In interviews, calculate value:
- "How much time does your team spend on PM overhead?" → 5 hrs/week
- Team of 5 × 5 hrs × $50/hr × 4 weeks = $5,000/month
- If you save 50% = $2,500/month value
- $49 × 5 users = $245/month = 10% of value saved
Value ratio: 10:1 → Price has room to increase
Step 4: Commitment Test
"We're launching soon. For $199 annual prepay (40% off), you'd get lifetime early-adopter pricing and input on the roadmap. Would you be interested?"
Track:
- How many say yes?
- What objections come up?
Hypothetical Results
| Method | Finding |
|---|---|
| Reference prices | Competitors: $10-30/user. Yours needs differentiation story. |
| Van Westendorp | Range: $29-79. OPP: $49. IDP: $39. |
| Value quantification | 10:1 value ratio at $49. Room for higher. |
| Commitment test | 4 of 10 prepaid at $199 ($50/user equiv) |
Recommendation
Launch at $39/user/month (annual: $29/user)
Rationale:
- At competitive upper range ($30 most expensive competitor)
- Inside Van Westendorp comfortable range
- Can test $49 with marketing-specific segments later
- Early customers locked in while you build brand
Pricing tiers:
- Starter: $39/user/month (1-10 users)
- Team: $29/user/month (11-50 users)
- Enterprise: Custom
Test plan:
- Launch at $39
- A/B test $49 with "marketing agency" segment in Month 2
- Grandfather early customers at launch price
---
Example 2: Consumer Product Pricing
Input:
"I'm launching a $150/week meal prep delivery service. Is this validated? My interviews showed people spend $100/week on groceries."
Output:
Pricing Analysis: Meal Prep Service at $150/week
Reference Price Problem
Current spending: $100/week on groceries Your price: $150/week
Gap: 50% increase from their reference price
This is a significant psychological hurdle. You're not competing with meal prep—you're competing with groceries.
Value Reframe Required
Wrong frame: "$150/week for food" Right frame: "$150/week for healthy eating + 5 hours of your time back"
Value calculation:
- Time saved: 5 hours/week × $30/hour = $150/week value
- Healthier eating: Lower healthcare costs, energy, etc.
- Total value: >$200/week
Price vs. Value: $150 for $200+ value = fair
Validation Approach
Question 1: Reference pricing "How much do you spend on food per week, including groceries and takeout?" → Most spend $150-250 when you include dining out
Question 2: Time value "How much is an hour of your time worth?" "Would you pay $30 to get an hour back?" → If yes, you have room at $150
Question 3: Commitment test "We're doing a 2-week trial at $125/week (no commitment after). Would you try it?" → Conversion rate = validation signal
Gabor-Granger Test Design
Test three prices:
- $99/week (loss leader to test demand curve)
- $125/week (compromise)
- $150/week (target)
Survey 30+ in each condition.
Expected finding hypothesis:
| Price | Intent | Weighted Demand |
|---|---|---|
| $99 | 60% | 48% |
| $125 | 45% | 34% |
| $150 | 30% | 22% |
Revenue optimization:
- $99 × 48% = $47.52/person expected
- $125 × 34% = $42.50/person expected
- $150 × 22% = $33.00/person expected
If this pattern holds → Price at $99-125, not $150.
Alternative Validation Signals
Strong validation for $150:
- They're already spending $150+ on food + takeout combined
- They've paid for similar services (HelloFresh, etc.) at $100+
- They'd prepay for a trial
- High earners with time scarcity
Weak validation:
- Most spend <$100 on groceries
- Never paid for meal services
- "Seems expensive"
- No urgency around time savings
Recommendation
Start at $125/week with trial offer
- Lower barrier to entry
- Build habit and reviews
- Raise to $150 after establishing value
- Premium tier at $175 for dietary customization
---
Example 3: B2B Pricing with Decision Maker Validation
Input:
"I'm selling to enterprises at $50K/year. How do I validate pricing when the buyer isn't the user?"
Output:
Enterprise Pricing Validation
The Challenge
- Users see value but don't control budget
- Buyers control budget but don't use the product
- $50K requires procurement/approval
Multi-Stakeholder Validation
Step 1: User Value Validation With end users, validate:
- Problem severity (8+/10)
- Solution fit (would use it)
- Value articulation (can describe ROI)
They become internal champions who sell to buyers.
Step 2: Buyer Price Validation
With budget holders, ask:
- "What's your budget for tools like this?"
- "What's the most you've spent on similar software?"
- "How does $50K compare to what you expected?"
- "What would it take to justify $50K internally?"
Step 3: Procurement Reality Check
- "At $50K, who needs to approve?"
- "What's the procurement process?"
- "What contract terms are standard?"
- "What would make this easier to approve?"
Price Anchoring for Enterprise
Anchor to cost, not features:
"Your team spends 20 hours/week on this process. At $100/hour loaded cost, that's $100K/year. This tool cuts that by 50%, saving $50K and freeing your team for higher-value work. The investment is $50K/year."
ROI story: 100% ROI in year 1.
Commitment Ladder
| Commitment Level | What You Ask | Validation Strength |
|---|---|---|
| Interest | "Can we demo to your team?" | Weak |
| Champion | "Would you advocate internally?" | Medium |
| Pilot | "Would you run a paid pilot?" | Strong |
| LOI | "Would you sign letter of intent?" | Strong |
| Prepay | "Would you prepay Q1?" | Very Strong |
Validation Signals for $50K
Validated if:
- 3+ LOIs or paid pilots at $50K
- Buyers say it's "within budget" or "expected"
- Clear ROI story they can articulate internally
- Procurement timeline is reasonable (not "next fiscal year")
Not validated if:
- "That's much more than we expected"
- "That would need board approval"
- "We've never spent that on a tool like this"
- No one will sign LOI
Price Testing Approach
Don't ask: "Would you pay $50K?" Instead: "Based on the value we discussed, we're thinking $50K/year. What's your reaction?"
Listen for:
- "That seems reasonable" → validated
- "Hmm, that's more than I expected" → probe what they expected
- "We'd need to see strong ROI" → they need the business case
- "That's out of our budget" → test lower or different segment
---
Checklists & Templates
Pricing Validation Plan Template
## Pricing Validation Plan
**Product:** _______________
**Target price:** _______________
**Launch date:** _______________
### Methods to Use
- [ ] Van Westendorp PSM (n=100+)
- [ ] Gabor-Granger (n=50+)
- [ ] Reference price research
- [ ] Value quantification
- [ ] Commitment testing
- [ ] A/B testing (if traffic available)
### Timeline
- Week 1-2: Customer interviews (reference prices, value)
- Week 3-4: Survey (Van Westendorp/Gabor-Granger)
- Week 5: Analysis and decision
- Week 6: Commitment testing
### Decision Criteria
Price validated if:
- Within Van Westendorp acceptable range
- Gabor-Granger shows >30% intent
- Reference prices support
- 3+ commitments obtained---
Van Westendorp Survey Template
## Van Westendorp Price Sensitivity Survey
**Product Description:**
[Clear description of product and value proposition]
**Screening:**
1. Are you a [target customer]? Y/N
2. Do you currently experience [problem]? Y/N
**Price Questions:**
Q1: At what price would you consider [product] to be so expensive
that you would NOT consider buying it?
$_______________
Q2: At what price would you consider [product] to be priced so low
that you would question its quality?
$_______________
Q3: At what price would you consider [product] starting to get expensive—
it's not out of the question, but you'd have to think about buying it?
$_______________
Q4: At what price would you consider [product] to be a bargain—
a great buy for the money?
$_______________
**Additional Context:**
Q5: What do you currently pay for [similar/alternative]?
$_______________
Q6: What would you expect a product like this to cost?
$_______________---
Skill Boundaries
What This Skill Does Well
- Structuring strategic analysis
- Identifying market opportunities
- Creating strategic frameworks
- Synthesizing competitive data
What This Skill Cannot Do
- Replace market research
- Guarantee strategic success
- Know proprietary competitor info
- Make executive decisions
References
- Van Westendorp, P. "NSS Price Sensitivity Meter" (1976)
- Gabor, A. & Granger, C. "Price as an Indicator of Quality" (1966)
- Simon, H. & Fassnacht, M. "Price Management" (2019)
- Ramanujam, M. & Tacke, G. "Monetizing Innovation" (2016)
- Poundstone, W. "Priceless: The Myth of Fair Value" (2010)
Related Skills
- solution-interview - Validate solution before pricing
- customer-discovery - Overall validation framework
- pricing-strategy - Strategic pricing decisions
- grand-slam-offers - Offer structure beyond price
- objection-mapping - Handle price objections
---
Skill Metadata
- Mode: centaur
name: pricing-validation
category: validation
subcategory: pricing-research
version: 1.0
author: MKTG Skills
source_expert: Van Westendorp, Gabor-Granger
source_work: Price Sensitivity Meter, Price Management
difficulty: intermediate
estimated_value: $5,000 pricing research project
tags: [pricing, validation, research, Van-Westendorp, willingness-to-pay, YC]
created: 2026-01-25
updated: 2026-01-25#!/usr/bin/env python3
"""
Pricing Validation Calculator - Van Westendorp PSM & Gabor-Granger analysis.
Based on Van Westendorp (1976) Price Sensitivity Meter methodology.
Usage:
python main.py van-westendorp data.csv
python main.py gabor-granger --prices 49,79,99,149 --responses 80,65,45,20
python main.py elasticity --base-price 99 --base-demand 100 --new-price 79 --new-demand 130
"""
import click
import json
from dataclasses import dataclass
from typing import Optional
from pathlib import Path
@dataclass
class VanWestendorpResult:
"""Van Westendorp Price Sensitivity Meter results."""
point_of_marginal_cheapness: float # PMC
point_of_marginal_expensiveness: float # PME
optimal_price_point: float # OPP
indifference_price_point: float # IPP
acceptable_price_range: tuple[float, float]
@dataclass
class GaborGrangerResult:
"""Gabor-Granger demand curve results."""
prices: list[float]
demands: list[float]
revenues: list[float]
optimal_price: float
optimal_revenue: float
elasticity_estimate: float
def analyze_van_westendorp(
too_cheap: list[float],
cheap: list[float],
expensive: list[float],
too_expensive: list[float]
) -> VanWestendorpResult:
"""
Analyze Van Westendorp PSM data.
Arguments:
too_cheap: "At what price would it be so cheap you'd doubt quality?"
cheap: "At what price would it start to seem like a bargain?"
expensive: "At what price would it start to seem expensive?"
too_expensive: "At what price would it be too expensive to consider?"
"""
# Sort all responses
too_cheap = sorted(too_cheap)
cheap = sorted(cheap)
expensive = sorted(expensive)
too_expensive = sorted(too_expensive)
# Get price range for analysis
all_prices = too_cheap + cheap + expensive + too_expensive
min_price = min(all_prices)
max_price = max(all_prices)
# Calculate cumulative percentages at each price point
def cumulative_pct(data: list[float], price: float, ascending: bool = True) -> float:
"""Calculate cumulative percentage at a price point."""
if ascending:
return sum(1 for p in data if p <= price) / len(data) * 100
else:
return sum(1 for p in data if p >= price) / len(data) * 100
# Find intersection points
# PMC: too_cheap (descending) crosses cheap (ascending)
# PME: expensive (ascending) crosses too_expensive (descending)
# OPP: too_cheap (descending) crosses too_expensive (descending)
# IPP: cheap (ascending) crosses expensive (ascending)
price_points = sorted(set(all_prices))
pmc = pme = opp = ipp = None
for i, price in enumerate(price_points[:-1]):
next_price = price_points[i + 1]
# Calculate cumulative percentages
tc_pct = cumulative_pct(too_cheap, price, ascending=False)
tc_next = cumulative_pct(too_cheap, next_price, ascending=False)
c_pct = cumulative_pct(cheap, price, ascending=True)
c_next = cumulative_pct(cheap, next_price, ascending=True)
e_pct = cumulative_pct(expensive, price, ascending=True)
e_next = cumulative_pct(expensive, next_price, ascending=True)
te_pct = cumulative_pct(too_expensive, price, ascending=False)
te_next = cumulative_pct(too_expensive, next_price, ascending=False)
# Find PMC (too_cheap desc crosses cheap asc)
if pmc is None and tc_pct >= c_pct and tc_next <= c_next:
pmc = (price + next_price) / 2
# Find PME (expensive asc crosses too_expensive desc)
if pme is None and e_pct <= te_pct and e_next >= te_next:
pme = (price + next_price) / 2
# Find OPP (too_cheap desc crosses too_expensive desc - minimum resistance)
if opp is None and tc_pct >= te_pct and tc_next <= te_next:
opp = (price + next_price) / 2
# Find IPP (cheap asc crosses expensive asc)
if ipp is None and c_pct <= e_pct and c_next >= e_next:
ipp = (price + next_price) / 2
# Fallbacks if intersections not found
pmc = pmc or min_price + (max_price - min_price) * 0.25
pme = pme or min_price + (max_price - min_price) * 0.75
opp = opp or (pmc + pme) / 2
ipp = ipp or (pmc + pme) / 2
return VanWestendorpResult(
point_of_marginal_cheapness=pmc,
point_of_marginal_expensiveness=pme,
optimal_price_point=opp,
indifference_price_point=ipp,
acceptable_price_range=(pmc, pme)
)
def analyze_gabor_granger(
prices: list[float],
demands: list[float]
) -> GaborGrangerResult:
"""
Analyze Gabor-Granger demand curve data.
Arguments:
prices: List of tested price points
demands: List of purchase intent percentages (0-100)
"""
revenues = [p * d for p, d in zip(prices, demands)]
max_revenue_idx = revenues.index(max(revenues))
optimal_price = prices[max_revenue_idx]
optimal_revenue = revenues[max_revenue_idx]
# Calculate price elasticity using midpoint method
if len(prices) >= 2:
p1, p2 = prices[0], prices[-1]
d1, d2 = demands[0], demands[-1]
avg_d = (d1 + d2) / 2
avg_p = (p1 + p2) / 2
if avg_d > 0 and avg_p > 0:
elasticity = ((d2 - d1) / avg_d) / ((p2 - p1) / avg_p)
else:
elasticity = 0
else:
elasticity = 0
return GaborGrangerResult(
prices=prices,
demands=demands,
revenues=revenues,
optimal_price=optimal_price,
optimal_revenue=optimal_revenue,
elasticity_estimate=elasticity
)
@click.group()
def cli():
"""Pricing Validation Calculator - Van Westendorp & Gabor-Granger."""
pass
@cli.command('van-westendorp')
@click.argument('data_file', type=click.Path(exists=True), required=False)
@click.option('--too-cheap', '-tc', help='Comma-separated "too cheap" responses')
@click.option('--cheap', '-c', help='Comma-separated "bargain" responses')
@click.option('--expensive', '-e', help='Comma-separated "expensive" responses')
@click.option('--too-expensive', '-te', help='Comma-separated "too expensive" responses')
def van_westendorp(
data_file: Optional[str],
too_cheap: Optional[str],
cheap: Optional[str],
expensive: Optional[str],
too_expensive: Optional[str]
):
"""Run Van Westendorp Price Sensitivity Meter analysis.
Provide either a JSON/CSV file or command-line data.
Example with CLI data:
python main.py van-westendorp --tc "10,15,20,25" --c "30,40,50,60" --e "80,90,100,110" --te "120,150,180,200"
"""
if data_file:
path = Path(data_file)
if path.suffix == '.json':
with open(path) as f:
data = json.load(f)
tc_data = data.get('too_cheap', [])
c_data = data.get('cheap', [])
e_data = data.get('expensive', [])
te_data = data.get('too_expensive', [])
else:
click.echo("Only JSON files supported currently")
return
elif all([too_cheap, cheap, expensive, too_expensive]):
tc_data = [float(x.strip()) for x in too_cheap.split(',')]
c_data = [float(x.strip()) for x in cheap.split(',')]
e_data = [float(x.strip()) for x in expensive.split(',')]
te_data = [float(x.strip()) for x in too_expensive.split(',')]
else:
click.echo("Provide either data_file or all four price response options")
return
result = analyze_van_westendorp(tc_data, c_data, e_data, te_data)
click.echo("\n Van Westendorp Price Sensitivity Meter")
click.echo(f" {'=' * 50}")
click.echo("\n Data Summary")
click.echo(f" {'-' * 50}")
click.echo(f" Responses analyzed: {len(tc_data)} per question")
click.echo(f" Price range tested: ${min(tc_data + c_data + e_data + te_data):.0f} - ${max(tc_data + c_data + e_data + te_data):.0f}")
click.echo("\n Key Price Points")
click.echo(f" {'-' * 50}")
click.echo(f" Point of Marginal Cheapness (PMC): ${result.point_of_marginal_cheapness:.2f}")
click.echo(f" Point of Marginal Expensiveness (PME): ${result.point_of_marginal_expensiveness:.2f}")
click.echo(f" Optimal Price Point (OPP): ${result.optimal_price_point:.2f}")
click.echo(f" Indifference Price Point (IPP): ${result.indifference_price_point:.2f}")
click.echo("\n Acceptable Price Range")
click.echo(f" {'-' * 50}")
click.echo(f" Range: ${result.acceptable_price_range[0]:.2f} - ${result.acceptable_price_range[1]:.2f}")
click.echo("\n Interpretation")
click.echo(f" {'-' * 50}")
click.echo(f" - Price below ${result.point_of_marginal_cheapness:.0f}: Quality concerns")
click.echo(f" - Price above ${result.point_of_marginal_expensiveness:.0f}: Too expensive for most")
click.echo(f" - Optimal price: ${result.optimal_price_point:.0f} (minimal price resistance)")
click.echo(f" - Safe pricing zone: ${result.point_of_marginal_cheapness:.0f} - ${result.point_of_marginal_expensiveness:.0f}")
@cli.command('gabor-granger')
@click.option('--prices', '-p', required=True, help='Comma-separated price points tested')
@click.option('--responses', '-r', required=True, help='Comma-separated purchase intent % at each price')
def gabor_granger(prices: str, responses: str):
"""Run Gabor-Granger demand curve analysis.
Example:
python main.py gabor-granger --prices "49,79,99,149" --responses "80,65,45,20"
"""
price_list = [float(x.strip()) for x in prices.split(',')]
demand_list = [float(x.strip()) for x in responses.split(',')]
if len(price_list) != len(demand_list):
click.echo("Error: Number of prices must match number of responses")
return
result = analyze_gabor_granger(price_list, demand_list)
click.echo("\n Gabor-Granger Demand Analysis")
click.echo(f" {'=' * 50}")
click.echo("\n Demand Curve")
click.echo(f" {'-' * 50}")
click.echo(f" {'Price':>10} {'Demand %':>12} {'Revenue Index':>15}")
click.echo(f" {'-' * 50}")
for i, (p, d, r) in enumerate(zip(result.prices, result.demands, result.revenues)):
marker = " <-- optimal" if p == result.optimal_price else ""
click.echo(f" ${p:>9.0f} {d:>11.0f}% {r:>14.0f}{marker}")
click.echo("\n Analysis")
click.echo(f" {'-' * 50}")
click.echo(f" Optimal Price: ${result.optimal_price:.0f}")
click.echo(f" Max Revenue Index: {result.optimal_revenue:.0f}")
click.echo(f" Price Elasticity: {result.elasticity_estimate:.2f}")
if result.elasticity_estimate < -1:
click.echo("\n Elasticity Interpretation: ELASTIC")
click.echo(" - Demand is sensitive to price changes")
click.echo(" - Consider lower prices for higher volume")
elif result.elasticity_estimate > -1:
click.echo("\n Elasticity Interpretation: INELASTIC")
click.echo(" - Demand is less sensitive to price")
click.echo(" - Room to increase prices")
@cli.command('elasticity')
@click.option('--base-price', '-bp', type=float, required=True, help='Original price')
@click.option('--base-demand', '-bd', type=float, required=True, help='Original demand/sales')
@click.option('--new-price', '-np', type=float, required=True, help='New price')
@click.option('--new-demand', '-nd', type=float, required=True, help='New demand/sales')
def elasticity(base_price: float, base_demand: float, new_price: float, new_demand: float):
"""Calculate price elasticity from before/after data.
Example:
python main.py elasticity --base-price 99 --base-demand 100 --new-price 79 --new-demand 130
"""
# Midpoint elasticity formula
avg_q = (base_demand + new_demand) / 2
avg_p = (base_price + new_price) / 2
pct_change_q = (new_demand - base_demand) / avg_q * 100
pct_change_p = (new_price - base_price) / avg_p * 100
if pct_change_p != 0:
elasticity_value = pct_change_q / pct_change_p
else:
elasticity_value = 0
base_revenue = base_price * base_demand
new_revenue = new_price * new_demand
revenue_change = new_revenue - base_revenue
revenue_change_pct = (revenue_change / base_revenue) * 100 if base_revenue > 0 else 0
click.echo("\n Price Elasticity Analysis")
click.echo(f" {'=' * 45}")
click.echo("\n Before vs After")
click.echo(f" {'-' * 45}")
click.echo(f" {'':15} {'Before':>12} {'After':>12}")
click.echo(f" {'-' * 45}")
click.echo(f" {'Price':15} ${base_price:>11.0f} ${new_price:>11.0f}")
click.echo(f" {'Demand':15} {base_demand:>12.0f} {new_demand:>12.0f}")
click.echo(f" {'Revenue':15} ${base_revenue:>11.0f} ${new_revenue:>11.0f}")
click.echo("\n Calculations")
click.echo(f" {'-' * 45}")
click.echo(f" Price Change: {pct_change_p:+.1f}%")
click.echo(f" Demand Change: {pct_change_q:+.1f}%")
click.echo(f" Price Elasticity: {elasticity_value:.2f}")
click.echo(f" Revenue Change: {revenue_change_pct:+.1f}% (${revenue_change:+,.0f})")
click.echo("\n Interpretation")
click.echo(f" {'-' * 45}")
abs_e = abs(elasticity_value)
if abs_e > 1:
click.echo(f" ELASTIC (|E| = {abs_e:.2f} > 1)")
click.echo(" - Demand is sensitive to price changes")
click.echo(" - 1% price change leads to >{:.1f}% demand change".format(abs_e))
if revenue_change > 0:
click.echo(" - Price decrease increased revenue (correct direction)")
else:
click.echo(" - Consider: Lower price may increase revenue")
elif abs_e < 1:
click.echo(f" INELASTIC (|E| = {abs_e:.2f} < 1)")
click.echo(" - Demand is not very sensitive to price")
click.echo(" - 1% price change leads to <{:.1f}% demand change".format(abs_e))
if new_price > base_price and revenue_change > 0:
click.echo(" - Price increase worked (demand held)")
else:
click.echo(" - Consider: Room to raise prices")
else:
click.echo(f" UNIT ELASTIC (|E| = {abs_e:.2f})")
click.echo(" - Revenue stays constant as price changes")
@cli.command('questions')
def questions():
"""Print Van Westendorp survey questions for your research."""
click.echo("\n Van Westendorp Survey Questions")
click.echo(f" {'=' * 60}")
click.echo("\n Use these 4 questions in your pricing research:")
click.echo(f" {'-' * 60}")
click.echo("""
Q1 - TOO CHEAP (Quality Doubt):
"At what price would you consider [product] to be priced so low
that you would feel the quality couldn't be very good?"
Q2 - CHEAP (Bargain):
"At what price would you consider [product] to be a bargain -
a great buy for the money?"
Q3 - EXPENSIVE (Getting Expensive):
"At what price would you consider [product] starting to get
expensive - not out of the question, but you'd have to think?"
Q4 - TOO EXPENSIVE (Prohibitive):
"At what price would you consider [product] to be so expensive
that you wouldn't consider buying it?"
""")
click.echo(f" {'-' * 60}")
click.echo(" Collect 100-200+ responses for reliable results.")
click.echo(" Export data as JSON with keys: too_cheap, cheap, expensive, too_expensive")
if __name__ == "__main__":
cli()
click>=8.0