/ sales-playbook / pricing_pattern_library.py
pricing_pattern_library.py
  1  #!/usr/bin/env python3
  2  """
  3  Value-Based Pricing: Pattern Library & Training
  4  
  5  A reference library of 10 proven value-based pricing patterns, usable as both
  6  a training tool and a real-time sales assistant.
  7  
  8  Usage:
  9      python3 pricing_pattern_library.py --list
 10      python3 pricing_pattern_library.py --pattern "anchor-with-data"
 11      python3 pricing_pattern_library.py --scenario "prospect is a $50M SaaS company spending $15K/mo on marketing"
 12      python3 pricing_pattern_library.py --quiz
 13  """
 14  
 15  import argparse
 16  import json
 17  import os
 18  import random
 19  import sys
 20  from datetime import datetime
 21  
 22  # ---------------------------------------------------------------------------
 23  # LLM Integration Stubs
 24  # ---------------------------------------------------------------------------
 25  
 26  
 27  def _call_llm(prompt: str, system_prompt: str = "") -> str:
 28      """
 29      Stub: Call LLM for scenario analysis.
 30  
 31      In production, replace with:
 32          POST https://api.anthropic.com/v1/messages  (ANTHROPIC_API_KEY)
 33          POST https://api.openai.com/v1/chat/completions  (OPENAI_API_KEY)
 34      """
 35      anthropic_key = os.environ.get("ANTHROPIC_API_KEY")
 36      openai_key = os.environ.get("OPENAI_API_KEY")
 37  
 38      if anthropic_key:
 39          # TODO: Implement real Anthropic API call
 40          # import requests
 41          # resp = requests.post(
 42          #     "https://api.anthropic.com/v1/messages",
 43          #     headers={"x-api-key": anthropic_key, "anthropic-version": "2023-06-01", "content-type": "application/json"},
 44          #     json={"model": "claude-sonnet-4-20250514", "max_tokens": 4096, "system": system_prompt, "messages": [{"role": "user", "content": prompt}]},
 45          # )
 46          # return resp.json()["content"][0]["text"]
 47          pass
 48  
 49      if openai_key:
 50          # TODO: Implement real OpenAI API call
 51          pass
 52  
 53      return None
 54  
 55  
 56  # ---------------------------------------------------------------------------
 57  # Pattern Library
 58  # ---------------------------------------------------------------------------
 59  # ALL examples are FULLY ANONYMIZED. No real company names, people, or revenue numbers.
 60  
 61  PATTERNS = {
 62      "anchor-with-data": {
 63          "name": "Anchor With Data",
 64          "tagline": "Open with their competitive data, not your pitch. Let the gap sell the urgency.",
 65          "description": (
 66              "Before you say a single word about what you do or what you charge, show the prospect "
 67              "their own competitive landscape. Pull their keyword rankings, traffic data, and "
 68              "competitor positions. When they see the gap between where they are and where their "
 69              "competitor is, the urgency sells itself. You're not pitching; you're diagnosing."
 70          ),
 71          "when_to_use": [
 72              "First call with any prospect who has meaningful organic competition",
 73              "When you need to justify a large deal size",
 74              "When the prospect thinks they're doing fine (they often don't know the gap)",
 75              "Especially effective with data-driven or technical decision makers",
 76          ],
 77          "example_dialogue": [
 78              "Rep: 'Before we talk about anything, I pulled some data I thought you'd find interesting. Mind if I share my screen?'",
 79              "Prospect: 'Sure, go ahead.'",
 80              "Rep: 'So here's where you rank for your top 10 money keywords. And here's where TechStart Inc ranks for those same keywords. Notice anything?'",
 81              "Prospect: '...they're ahead on almost all of them.'",
 82              "Rep: 'Right. And here's what that gap means in traffic. They're getting roughly 45,000 visits per month from these keywords alone. You're getting about 8,000. That's 37,000 visits per month that could be yours.'",
 83              "Prospect: 'I didn't realize the gap was that big.'",
 84              "Rep: 'Most people don't until they see it. Want me to walk through what closing that gap would look like?'",
 85          ],
 86          "common_mistakes": [
 87              "Showing data AFTER pitching your services (loses the anchoring effect)",
 88              "Using data that's not relevant to their specific business goals",
 89              "Overwhelming with too many data points instead of focusing on 3-5 killer gaps",
 90              "Not connecting the data to dollar values (traffic alone doesn't motivate; traffic value does)",
 91          ],
 92          "success_rate_notes": "Highest-converting opener in our playbook. Calls that lead with competitive data close at 2.3x the rate of calls that lead with capabilities.",
 93      },
 94      "tiered-packaging": {
 95          "name": "Tiered Packaging (S/M/L + Performance)",
 96          "tagline": "Always present 3-4 options. Anchor high. Land in the middle.",
 97          "description": (
 98              "Never present a single price. Always offer 3-4 tiers: a premium anchor (Powerhouse), "
 99              "your target tier (Value), a stripped-down floor (Baseline), and a performance option "
100              "(skin in the game). The premium makes the target look reasonable. The baseline creates "
101              "a floor. The performance option catches prospects who stall on fixed pricing."
102          ),
103          "when_to_use": [
104              "Every proposal presentation, without exception",
105              "Especially when moving from a small engagement to a larger one",
106              "When competing against agencies that only present one price",
107              "When the prospect's budget is unclear",
108          ],
109          "example_dialogue": [
110              "Rep: 'Based on what you've told me, I've put together four options. Let me walk you through them.'",
111              "Rep: 'Option 1 is our Powerhouse package at $110,000 per month. This is the full-service, senior-strategist-involved, aggressive-growth option. Everything we talked about plus dedicated executive alignment.'",
112              "Rep: 'Option 2 is our Value package at $80,000 per month. This covers all the critical growth levers we discussed. It's where most of our successful clients land.'",
113              "Rep: 'Option 3 is our Baseline at $35,000 per month. This focuses on the top 2-3 priorities. Good for proving the model before scaling.'",
114              "Rep: 'And Option 4 is our Performance package. Lower base at $28,000 per month, but with bonus triggers tied to traffic and revenue outcomes. We put skin in the game.'",
115              "Prospect: 'Tell me more about Option 2.'",
116              "(This is the expected response. The anchor worked.)",
117          ],
118          "common_mistakes": [
119              "Starting with the cheapest option (kills the anchor effect)",
120              "Making tiers too similar (if they can't tell the difference, they'll pick the cheapest)",
121              "Not having clear 'what's not included' for lower tiers (scarcity drives upgrades)",
122              "Presenting more than 4 options (decision paralysis)",
123          ],
124          "success_rate_notes": "Deals presented with tiered options average 40% higher closed value vs. single-price proposals. The Value tier is selected ~55% of the time when the anchor is presented first.",
125      },
126      "competitive-ego-trigger": {
127          "name": "Competitive Ego Trigger",
128          "tagline": "'Your competitor ranks #1 for [keyword]. You're #14.' Works on every competitive CEO.",
129          "description": (
130              "Competitive business leaders can't stand losing. When you show them specific, "
131              "concrete data about where a competitor is beating them, it triggers an emotional "
132              "response that bypasses rational objections. This isn't manipulation; it's showing "
133              "them reality they didn't have access to. The key is specificity."
134          ),
135          "when_to_use": [
136              "When the decision maker is a CEO, founder, or other competitive leader",
137              "When you have clear data showing competitor advantages",
138              "When the prospect thinks they're 'doing okay' with their current approach",
139              "NOT when the prospect is already anxious (don't pile on)",
140          ],
141          "example_dialogue": [
142              "Rep: 'I looked at your keyword landscape vs. NovaPay. For the keyword \"enterprise payment processing,\" NovaPay ranks #1. You're #14.'",
143              "Prospect: 'We're #14? That can't be right.'",
144              "Rep: 'I double-checked. Here's the screenshot from today. And for \"B2B payment solutions,\" they're #2. You're not in the top 50.'",
145              "Prospect: '...how is that possible? We have a better product.'",
146              "Rep: 'I hear that a lot. Better product doesn't automatically mean better search presence. The good news is, these gaps are closeable. Want me to show you what it would take?'",
147          ],
148          "common_mistakes": [
149              "Being vague ('your competitors are ahead') instead of specific ('#1 vs #14 for [keyword]')",
150              "Using this pattern when the competitor is a 10x larger company (makes the gap feel insurmountable)",
151              "Not having a solution ready (trigger without a path forward just causes frustration)",
152              "Overusing it (pick 2-3 killer examples, not 20)",
153          ],
154          "success_rate_notes": "Triggers a strong emotional response in ~80% of CEO/founder calls. Follow-up meeting request rate increases by 60% when competitive data is presented vs. generic capability pitches.",
155      },
156      "strategic-involvement-upsell": {
157          "name": "Strategic Involvement Upsell",
158          "tagline": "CEO/senior involvement is the premium lever. Same team, add strategy = 3-5x price.",
159          "description": (
160              "The biggest pricing lever isn't more deliverables. It's senior strategic involvement. "
161              "A team executing SEO is worth $15-25K/mo. That same team with a dedicated senior "
162              "strategist who joins leadership meetings, aligns marketing with business strategy, "
163              "and provides executive-level guidance is worth $60-100K/mo. Same execution, different value layer."
164          ),
165          "when_to_use": [
166              "When moving a prospect from a mid-tier to premium engagement",
167              "When the prospect values strategic guidance over tactical execution",
168              "When you're competing against cheaper agencies (you can't win on execution cost; win on strategic value)",
169              "When the prospect's CEO or C-suite is involved in the buying process",
170          ],
171          "example_dialogue": [
172              "Prospect: 'What's the difference between your $30K and $80K packages? Is it just more content?'",
173              "Rep: 'Great question. The execution team is actually very similar. The difference is strategic involvement. At $80K, you get a dedicated senior strategist who joins your leadership team calls, aligns our work with your quarterly business objectives, and provides the kind of strategic guidance that turns marketing from a cost center into a growth engine.'",
174              "Rep: 'Think of it this way: at $30K, we're executing a playbook. At $80K, we're building the playbook WITH your leadership team and adapting it in real-time as the business evolves.'",
175              "Prospect: 'That makes sense. Our current agency just executes what we tell them.'",
176              "Rep: 'And that's exactly the gap we'd fill.'",
177          ],
178          "common_mistakes": [
179              "Positioning the upsell as 'more stuff' instead of 'different level of involvement'",
180              "Not having genuine senior talent to back the claim (this falls apart fast if you oversell)",
181              "Jumping to the strategic pitch before establishing execution credibility",
182              "Not quantifying the value of strategic alignment (tie it to business outcomes, not just marketing metrics)",
183          ],
184          "success_rate_notes": "The strategic involvement lever is the #1 driver of deals moving from $10-20K/mo to $50-100K/mo range. Average deal size increases 3.2x when strategic involvement is successfully positioned.",
185      },
186      "bridge-offer": {
187          "name": "Bridge Offer",
188          "tagline": "'You'll miss Q1 if you hire internally. We bridge the gap.' Creates urgency without being pushy.",
189          "description": (
190              "When a prospect says they want to build in-house, don't fight it. Agree, then show "
191              "them the timeline reality. Hiring takes 3-6 months. Onboarding takes 2-3 more. "
192              "Meanwhile, their competitors aren't waiting. Position yourself as the bridge: start "
193              "now, build momentum, and hand off when their team is ready (or just keep going because "
194              "the results are too good to stop)."
195          ),
196          "when_to_use": [
197              "When the prospect says 'we want to build this capability in-house'",
198              "When there's a clear time-sensitive opportunity (seasonal, competitive, market window)",
199              "When the prospect is comparing your cost to a hire's salary (reframe the comparison)",
200              "Works especially well in tight labor markets",
201          ],
202          "example_dialogue": [
203              "Prospect: 'We're actually thinking about hiring a Head of SEO internally.'",
204              "Rep: 'That's smart. Good SEO leadership is valuable. Quick question: when are you hoping to have that person fully ramped and producing results?'",
205              "Prospect: 'Ideally by Q2.'",
206              "Rep: 'Here's what I typically see: the search takes 2-3 months, then 2-3 months to ramp. So realistically, you're looking at Q3 or Q4 before they're fully contributing. Meanwhile, CloudRetail and your other competitors are investing heavily right now. We can bridge that gap. Start immediately, build the foundation, and either hand off to your new hire or keep working alongside them.'",
207              "Prospect: 'Hm, I hadn't thought about the ramp time.'",
208              "Rep: 'Most people don't. The bridge model de-risks it for you.'",
209          ],
210          "common_mistakes": [
211              "Arguing against in-house (makes you seem threatened)",
212              "Not acknowledging that in-house is a valid long-term strategy",
213              "Failing to quantify the cost of delay (make it concrete: 'every month without action is X in lost traffic value')",
214              "Not offering a genuine transition plan (if you promise to hand off, have a plan for it)",
215          ],
216          "success_rate_notes": "Converts ~35% of 'we want to hire in-house' objections into bridge engagements. Average bridge engagement lasts 8+ months (vs. the expected 3-4) because results create retention.",
217      },
218      "performance-skin-in-game": {
219          "name": "Performance Skin-in-Game",
220          "tagline": "Lower base + bonus on outcomes. Shows confidence. Often closes deals that stall on fixed pricing.",
221          "description": (
222              "When a prospect stalls on a fixed monthly fee, offer a performance structure: lower "
223              "base price + bonus triggers tied to specific outcomes. This shows confidence in your "
224              "ability to deliver and aligns your incentives with theirs. It also reframes the "
225              "conversation from 'how much does this cost' to 'what are we both willing to bet on.'"
226          ),
227          "when_to_use": [
228              "When the prospect says 'I love the plan but the price is too high'",
229              "When you're confident in your ability to deliver measurable results",
230              "When the prospect is risk-averse or has been burned by agencies before",
231              "When competing against cheaper agencies (you're not cheaper; you're more confident)",
232          ],
233          "example_dialogue": [
234              "Prospect: 'I like everything you've shown me but $80K per month is a big commitment given our past experience with agencies.'",
235              "Rep: 'I hear you. And I respect that you've been burned before. Here's what I'd suggest: we do a performance structure. Base of $35K per month covers our team and core execution. Then we set bonus triggers: if organic traffic increases 50% from baseline, that's a 15% bonus. If revenue attributed to organic exceeds 3x the monthly investment, that's another 20%.'",
236              "Rep: 'So if we don't deliver, you're at $35K. If we crush it, we're closer to $55K, but you're making multiples of that in return. We only win big when you win big.'",
237              "Prospect: 'That's actually fair. You're putting your money where your mouth is.'",
238              "Rep: 'Exactly. And frankly, we set the triggers where we expect to hit them. We wouldn't offer this if we didn't believe in the plan.'",
239          ],
240          "common_mistakes": [
241              "Setting bonus triggers that are easy to game (use business outcomes, not vanity metrics)",
242              "Making the base too low (you still need to be profitable at the base)",
243              "Not defining measurement methodology upfront (this causes disputes later)",
244              "Offering performance pricing when you're not confident in results (it will backfire)",
245          ],
246          "success_rate_notes": "Closes ~45% of deals that stall on fixed pricing. Average deal value ends up within 10% of the original fixed proposal because bonuses are typically hit.",
247      },
248      "value-math-on-screen": {
249          "name": "Value Math on Screen",
250          "tagline": "'If we move this keyword from #14 to #3, that's $X/mo in traffic value.' Make the ROI visual and obvious.",
251          "description": (
252              "Don't just tell them the ROI. Show them the math. On screen. In real-time. "
253              "Pull up their keywords, show the current position, the target position, the search "
254              "volume, the CPC, and calculate the traffic value live. When the prospect watches "
255              "the number build up keyword by keyword, they're selling themselves."
256          ),
257          "when_to_use": [
258              "During any pricing discussion (make the value visible before discussing cost)",
259              "When the prospect asks 'what kind of results can we expect?'",
260              "When you need to justify a large deal size",
261              "When competing against cheaper alternatives (show what the cheap option misses)",
262          ],
263          "example_dialogue": [
264              "Rep: 'Let me show you the math on just your top 5 keywords. [shares screen]'",
265              "Rep: 'Keyword 1: \"enterprise analytics platform.\" You're #14, getting roughly 200 visits/mo. If we move you to #3, that's 1,800 visits/mo. At a CPC of $18.50, that's $33,300/mo in paid equivalent value. Just from one keyword.'",
266              "Rep: 'Keyword 2: \"business intelligence software.\" You're #22, getting about 50 visits/mo. Position #3 would be 2,400 visits. At $22 CPC, that's $52,800/mo.'",
267              "Rep: 'Just these 5 keywords represent $X/mo in traffic value. Your total keyword universe is much larger.'",
268              "Prospect: 'When you put it that way, the investment makes a lot more sense.'",
269          ],
270          "common_mistakes": [
271              "Using unrealistic targets (don't promise #1 for everything; #3-5 is more credible)",
272              "Forgetting to mention this is paid equivalent value, not guaranteed revenue",
273              "Not accounting for the time it takes to achieve these rankings",
274              "Showing the math without connecting it to business outcomes (traffic value → leads → revenue)",
275          ],
276          "success_rate_notes": "Deals where value math is shown on screen close at 2.1x the rate of deals where ROI is just mentioned verbally. Average deal size is 35% higher when the math is visible.",
277      },
278      "compound-effect-close": {
279          "name": "Compound Effect Close",
280          "tagline": "'SEO + CRO + content compound on each other. Doing one without the others leaves money on the table.' Justifies the full package.",
281          "description": (
282              "When a prospect wants to cherry-pick individual services, show them how the services "
283              "compound on each other. SEO drives traffic, CRO converts it, content fuels both. "
284              "Doing SEO without CRO means you're driving traffic to a leaky funnel. Doing CRO "
285              "without SEO means you're optimizing a trickle. The math only works when they compound."
286          ),
287          "when_to_use": [
288              "When the prospect wants 'just SEO' or 'just paid' (they're leaving money on the table)",
289              "When justifying a multi-service package over a single-service engagement",
290              "When the prospect is comparing your multi-service price to a single-service competitor",
291              "When you need to prevent scope reduction during negotiation",
292          ],
293          "example_dialogue": [
294              "Prospect: 'Can we start with just the SEO piece? We'll add content and CRO later.'",
295              "Rep: 'You can, and here's what that looks like. SEO alone will move your rankings, but without optimized content, the rankings plateau. And without CRO, you're driving more traffic to a funnel that converts at the same rate.'",
296              "Rep: 'Here's the compound math: SEO alone might give you a 40% traffic increase. Add content, and it's 80% because you're feeding the SEO engine. Add CRO, and even though traffic is the same, leads might double because conversion rate improves. The total impact of all three is roughly 4x what SEO alone delivers. Not 3x, 4x, because they compound.'",
297              "Prospect: 'I see your point. What does the combined package look like?'",
298          ],
299          "common_mistakes": [
300              "Not having the math to back up the compounding claim (be specific, not hand-wavy)",
301              "Refusing to do single services at all (some clients need to start small; offer a path to scale)",
302              "Overselling the compound effect (4x is realistic; 10x is not credible)",
303              "Not having case study data showing compound vs. single-service results",
304          ],
305          "success_rate_notes": "Multi-service proposals using the compound effect framing have a 28% higher close rate and 2.2x average deal value vs. single-service proposals.",
306      },
307      "reference-customer-drop": {
308          "name": "Reference Customer Drop",
309          "tagline": "'One of our clients ranks #1 for [hard keyword]. Happy to connect you.' Social proof at the right moment.",
310          "description": (
311              "The most powerful form of social proof in B2B sales isn't a logo wall or a case study "
312              "PDF. It's a specific, verifiable result dropped at exactly the right moment in the "
313              "conversation, followed by an offer to connect directly. It turns abstract credibility "
314              "into concrete confidence."
315          ),
316          "when_to_use": [
317              "When the prospect expresses skepticism ('can you really do that?')",
318              "When discussing a specific outcome and you have a matching reference",
319              "After showing the value math (proof that the math converts to reality)",
320              "When competing against established agencies (proof beats reputation)",
321          ],
322          "example_dialogue": [
323              "Prospect: 'Those numbers look great on paper, but can you actually get us to page 1 for these keywords?'",
324              "Rep: 'Fair question. One of our clients, a mid-market SaaS company similar to yours, ranks #1 for \"enterprise workflow automation.\" That keyword alone drives over 3,000 visits per month for them. They started at #18.'",
325              "Prospect: 'How long did that take?'",
326              "Rep: 'About 7 months to break into the top 3, 11 months to hit #1. Happy to connect you with their marketing director if you'd like to hear it firsthand.'",
327              "Prospect: 'That would be great, actually.'",
328          ],
329          "common_mistakes": [
330              "Dropping references too early (before the prospect cares about the specific outcome)",
331              "Being vague ('we have great clients') instead of specific ('ranks #1 for [keyword]')",
332              "Not having the reference customer prepped and willing to take the call",
333              "Using the same reference for every prospect (match the reference to the prospect's industry/size)",
334          ],
335          "success_rate_notes": "Deals where a reference call happens close at 3.4x the rate of deals without reference engagement. The key is timing: reference drops work best after value math, not before.",
336      },
337      "in-house-team-framing": {
338          "name": "In-House Team Framing",
339          "tagline": "'Think of us as your in-house team, not a vendor.' Reframes the relationship and justifies premium pricing.",
340          "description": (
341              "When a prospect compares your fee to another agency's fee, you're in a commodity "
342              "conversation you can't win. Reframe: you're not a vendor, you're their in-house "
343              "marketing team, without the overhead of recruiting, salaries, benefits, management, "
344              "and ramp time. This changes the comparison from 'agency A vs. agency B' to 'build "
345              "internally vs. deploy a ready-made team.'"
346          ),
347          "when_to_use": [
348              "When the prospect compares your pricing to cheaper agencies",
349              "When the prospect is considering building in-house as an alternative",
350              "When you need to justify premium pricing vs. commodity competition",
351              "When the prospect values integration and strategic alignment over task execution",
352          ],
353          "example_dialogue": [
354              "Prospect: 'You're quite a bit more expensive than the other agencies we've talked to.'",
355              "Rep: 'I appreciate the transparency. Let me reframe the comparison. The other agencies will execute tasks you assign. We integrate as your marketing team. Think about what it would cost to hire a senior SEO lead, a content strategist, a CRO specialist, and a paid media manager in-house. You're looking at $500-700K per year in fully loaded salary, plus 3-6 months to recruit and ramp each one.'",
356              "Rep: 'For $80K per month, you get that entire team, already trained, already working together, with systems and processes built from working with dozens of companies like yours. No recruiting. No ramp time. No management overhead. And if it's not working, you can walk away. Try doing that with four full-time hires.'",
357              "Prospect: 'When you put it against hiring costs, it's actually not that different.'",
358              "Rep: 'It's usually less. And you get results faster because we're not starting from zero.'",
359          ],
360          "common_mistakes": [
361              "Using this framing when you can't actually deliver at an in-house team level",
362              "Not knowing the actual salary benchmarks for the roles you're replacing (do the math for their market)",
363              "Comparing to junior hires (compare to the senior talent you're actually providing)",
364              "Not backing it up with integration practices (slack channels, meeting cadences, shared dashboards)",
365          ],
366          "success_rate_notes": "The in-house team framing shifts the prospect's mental comparison from 'agency cost' to 'team cost,' typically increasing acceptable price range by 40-60%. Most effective with companies that have recently struggled to hire marketing talent.",
367      },
368  }
369  
370  
371  # ---------------------------------------------------------------------------
372  # Quiz Mode
373  # ---------------------------------------------------------------------------
374  
375  QUIZ_SCENARIOS = [
376      {
377          "scenario": "A prospect says: 'We like what you're proposing, but your price is about 30% higher than the other agency we're talking to. Can you match their price?'",
378          "best_pattern": "in-house-team-framing",
379          "also_applicable": ["tiered-packaging", "performance-skin-in-game"],
380          "explanation": "Don't compete on price. Reframe the comparison from agency-vs-agency to agency-vs-hiring. If they're comparing you to a cheaper agency, they're thinking about vendors. Shift them to thinking about a team.",
381      },
382      {
383          "scenario": "You're 10 minutes into a first call with the CEO of a mid-market SaaS company. She seems interested but hasn't expressed any specific pain. How do you create urgency?",
384          "best_pattern": "anchor-with-data",
385          "also_applicable": ["competitive-ego-trigger", "value-math-on-screen"],
386          "explanation": "Lead with data. Show her competitive landscape before pitching. The data will surface pain she didn't know she had. Follow up with competitive triggers if she's the competitive type.",
387      },
388      {
389          "scenario": "A prospect on a $15K/mo engagement asks: 'What would it look like to do more with you?' They're happy with results.",
390          "best_pattern": "strategic-involvement-upsell",
391          "also_applicable": ["compound-effect-close", "tiered-packaging"],
392          "explanation": "Don't just offer more deliverables. Offer a different level of engagement: senior strategic involvement, executive alignment, integrated planning. Same team, higher value layer.",
393      },
394      {
395          "scenario": "The VP of Marketing says: 'We've been burned by agencies before. Last one promised the world and delivered nothing. How are you different?'",
396          "best_pattern": "performance-skin-in-game",
397          "also_applicable": ["reference-customer-drop", "value-math-on-screen"],
398          "explanation": "They're risk-averse for good reason. Performance pricing puts your money where your mouth is. Follow with a reference customer who can vouch for results.",
399      },
400      {
401          "scenario": "A prospect wants to hire you for SEO only, even though you know their conversion rate is terrible. They'd get more traffic to a broken funnel.",
402          "best_pattern": "compound-effect-close",
403          "also_applicable": ["value-math-on-screen", "tiered-packaging"],
404          "explanation": "Show the compound math. SEO alone = 40% lift. SEO + CRO = 4x the business impact. Make it clear that doing one without the other leaves money on the table.",
405      },
406      {
407          "scenario": "The prospect says: 'We're planning to hire a Head of Content and a senior SEO manager. We think we can do this in-house for less.'",
408          "best_pattern": "bridge-offer",
409          "also_applicable": ["in-house-team-framing", "strategic-involvement-upsell"],
410          "explanation": "Don't fight the in-house plan. Agree it's smart, then show the timeline reality. Hiring + ramp = 6-9 months. Bridge the gap now, build momentum, and hand off (or keep going because results are too good to stop).",
411      },
412      {
413          "scenario": "You're presenting a $75K/mo proposal. The prospect says: 'We can see the value, but we only have $40K/mo approved for this quarter.'",
414          "best_pattern": "tiered-packaging",
415          "also_applicable": ["performance-skin-in-game", "bridge-offer"],
416          "explanation": "This is exactly why you have tiers. Present the Baseline at ~$35K with a clear path to scale. Or offer Performance pricing with a lower base and bonus triggers. Never just discount.",
417      },
418      {
419          "scenario": "The prospect is skeptical that you can rank for a highly competitive keyword in their industry. 'Everyone says they can do SEO. Nobody delivers.'",
420          "best_pattern": "reference-customer-drop",
421          "also_applicable": ["value-math-on-screen", "anchor-with-data"],
422          "explanation": "Don't argue. Prove. Drop a specific, verifiable reference: 'One of our clients ranks #1 for [similar hard keyword]. Started at #22. Took 9 months. Happy to connect you with them.'",
423      },
424  ]
425  
426  
427  def list_patterns() -> str:
428      """List all patterns with descriptions."""
429      lines = ["# Value-Based Pricing Pattern Library", ""]
430      lines.append(f"**{len(PATTERNS)} patterns available**")
431      lines.append("")
432      for i, (key, p) in enumerate(PATTERNS.items(), 1):
433          lines.append(f"## {i}. {p['name']}")
434          lines.append(f"*{p['tagline']}*")
435          lines.append("")
436          lines.append(f"**When to use:** {p['when_to_use'][0]}")
437          lines.append(f"**Key insight:** {p['success_rate_notes'][:100]}...")
438          lines.append(f"**Details:** `python3 pricing_pattern_library.py --pattern \"{key}\"`")
439          lines.append("")
440      return "\n".join(lines)
441  
442  
443  def get_pattern(pattern_key: str) -> str:
444      """Get detailed breakdown of a specific pattern."""
445      # Try exact match first, then fuzzy
446      key = pattern_key.lower().replace(" ", "-").replace("_", "-")
447      if key not in PATTERNS:
448          # Try partial match
449          matches = [k for k in PATTERNS if key in k or key in PATTERNS[k]["name"].lower()]
450          if len(matches) == 1:
451              key = matches[0]
452          elif len(matches) > 1:
453              return f"Multiple matches: {', '.join(matches)}. Be more specific."
454          else:
455              return f"Pattern not found: '{pattern_key}'. Use --list to see all patterns."
456  
457      p = PATTERNS[key]
458      lines = [f"# {p['name']}", f"*{p['tagline']}*", ""]
459      lines.append("## Description")
460      lines.append(p["description"])
461      lines.append("")
462  
463      lines.append("## When to Use")
464      for w in p["when_to_use"]:
465          lines.append(f"- {w}")
466      lines.append("")
467  
468      lines.append("## Example Dialogue")
469      for d in p["example_dialogue"]:
470          lines.append(f"> {d}")
471      lines.append("")
472  
473      lines.append("## Common Mistakes")
474      for m in p["common_mistakes"]:
475          lines.append(f"- āŒ {m}")
476      lines.append("")
477  
478      lines.append("## Success Rate Notes")
479      lines.append(p["success_rate_notes"])
480  
481      return "\n".join(lines)
482  
483  
484  def analyze_scenario(scenario: str) -> str:
485      """Analyze a scenario and recommend patterns (uses LLM if available, else rule-based)."""
486      # Try LLM first
487      pattern_summaries = "\n".join(
488          f"- {key}: {p['name']} - {p['tagline']}" for key, p in PATTERNS.items()
489      )
490  
491      llm_prompt = f"""Given this sales scenario:
492  
493  "{scenario}"
494  
495  And these available value-based pricing patterns:
496  {pattern_summaries}
497  
498  Recommend which 2-3 patterns to apply, in priority order. For each:
499  1. Which pattern and why it fits
500  2. Specific dialogue to use in this scenario
501  3. What to watch out for
502  
503  Be specific and actionable. Use the pattern names exactly."""
504  
505      llm_result = _call_llm(llm_prompt, system_prompt="You are an expert B2B sales coach specializing in value-based pricing.")
506  
507      if llm_result:
508          return f"# Scenario Analysis\n\n**Scenario:** {scenario}\n\n{llm_result}"
509  
510      # Fallback: keyword-based pattern matching
511      scenario_lower = scenario.lower()
512      scored_patterns = []
513  
514      keywords_map = {
515          "anchor-with-data": ["data", "first call", "discovery", "don't know", "competitive", "landscape", "research"],
516          "tiered-packaging": ["budget", "price", "options", "tiers", "proposal", "packages", "how much"],
517          "competitive-ego-trigger": ["competitor", "behind", "losing", "rival", "beating", "ceo", "founder"],
518          "strategic-involvement-upsell": ["expand", "more", "grow", "strategy", "strategic", "upsell", "upgrade"],
519          "bridge-offer": ["in-house", "hire", "internal", "build", "recruit", "team"],
520          "performance-skin-in-game": ["risk", "burned", "skeptic", "trust", "prove", "guarantee", "performance"],
521          "value-math-on-screen": ["roi", "results", "expect", "numbers", "value", "worth", "justify"],
522          "compound-effect-close": ["just seo", "just one", "single", "cherry pick", "only", "one service"],
523          "reference-customer-drop": ["proof", "results", "show me", "example", "case study", "who else"],
524          "in-house-team-framing": ["expensive", "cheaper", "agency", "compare", "cost", "other agencies"],
525      }
526  
527      for key, keywords in keywords_map.items():
528          score = sum(1 for kw in keywords if kw in scenario_lower)
529          if score > 0:
530              scored_patterns.append((key, score))
531  
532      scored_patterns.sort(key=lambda x: x[1], reverse=True)
533      top_patterns = scored_patterns[:3] if scored_patterns else list(PATTERNS.keys())[:3]
534  
535      lines = [f"# Scenario Analysis", "", f"**Scenario:** {scenario}", ""]
536      lines.append("*Analysis: rule-based (set ANTHROPIC_API_KEY or OPENAI_API_KEY for LLM-powered analysis)*")
537      lines.append("")
538      lines.append("## Recommended Patterns (in priority order)")
539      lines.append("")
540      for i, (key, score) in enumerate(top_patterns, 1):
541          p = PATTERNS[key]
542          lines.append(f"### {i}. {p['name']}")
543          lines.append(f"*{p['tagline']}*")
544          lines.append("")
545          lines.append(f"**Why this fits:** {p['when_to_use'][0]}")
546          lines.append("")
547          lines.append("**Key dialogue:**")
548          for d in p["example_dialogue"][:3]:
549              lines.append(f"> {d}")
550          lines.append("")
551          lines.append(f"**Watch out for:** {p['common_mistakes'][0]}")
552          lines.append("")
553  
554      return "\n".join(lines)
555  
556  
557  def run_quiz():
558      """Interactive quiz mode."""
559      print("# šŸŽÆ Value-Based Pricing Pattern Quiz")
560      print("I'll present scenarios. You identify the best pattern to apply.")
561      print(f"({len(QUIZ_SCENARIOS)} scenarios available)")
562      print()
563  
564      # Shuffle scenarios
565      scenarios = list(QUIZ_SCENARIOS)
566      random.shuffle(scenarios)
567  
568      correct = 0
569      total = 0
570  
571      pattern_names = {k: PATTERNS[k]["name"] for k in PATTERNS}
572      name_list = "\n".join(f"  {i+1}. {name} ({key})" for i, (key, name) in enumerate(pattern_names.items()))
573  
574      for i, quiz in enumerate(scenarios):
575          print(f"---")
576          print(f"## Scenario {i + 1}/{len(scenarios)}")
577          print()
578          print(f"  {quiz['scenario']}")
579          print()
580          print(f"Which pattern would you apply? (type the number or name)")
581          print(name_list)
582          print()
583  
584          try:
585              answer = input("Your answer: ").strip().lower()
586          except (EOFError, KeyboardInterrupt):
587              print("\n\nQuiz ended early.")
588              break
589  
590          # Match answer
591          matched_key = None
592          # Try number
593          try:
594              idx = int(answer) - 1
595              keys = list(PATTERNS.keys())
596              if 0 <= idx < len(keys):
597                  matched_key = keys[idx]
598          except ValueError:
599              pass
600  
601          # Try name/key match
602          if not matched_key:
603              for key in PATTERNS:
604                  if answer in key or answer in PATTERNS[key]["name"].lower():
605                      matched_key = key
606                      break
607  
608          total += 1
609          if matched_key == quiz["best_pattern"]:
610              correct += 1
611              print(f"\nāœ… Correct! {PATTERNS[quiz['best_pattern']]['name']}")
612          elif matched_key in quiz["also_applicable"]:
613              correct += 0.5
614              print(f"\n🟔 Good choice! {PATTERNS[matched_key]['name']} works here.")
615              print(f"   Best pattern: {PATTERNS[quiz['best_pattern']]['name']}")
616          else:
617              print(f"\nāŒ Not the best fit.")
618              print(f"   Best pattern: {PATTERNS[quiz['best_pattern']]['name']}")
619  
620          print(f"\n**Why:** {quiz['explanation']}")
621          print()
622  
623          if i < len(scenarios) - 1:
624              try:
625                  cont = input("Continue? (y/n): ").strip().lower()
626                  if cont == "n":
627                      break
628              except (EOFError, KeyboardInterrupt):
629                  break
630              print()
631  
632      # Score
633      print(f"\n---")
634      print(f"## Final Score: {correct}/{total}")
635      pct = (correct / total * 100) if total > 0 else 0
636      if pct >= 80:
637          print("šŸ† Expert level. You know the playbook.")
638      elif pct >= 60:
639          print("šŸ‘ Solid. Review the patterns you missed.")
640      elif pct >= 40:
641          print("šŸ“š Getting there. Run `--list` and study the patterns.")
642      else:
643          print("šŸ”„ Time to study. Run `--pattern <name>` for deep dives on each pattern.")
644  
645  
646  def main():
647      parser = argparse.ArgumentParser(
648          description="Value-Based Pricing: Pattern Library & Training",
649          formatter_class=argparse.RawDescriptionHelpFormatter,
650          epilog="""
651  Examples:
652    python3 pricing_pattern_library.py --list
653    python3 pricing_pattern_library.py --pattern "anchor-with-data"
654    python3 pricing_pattern_library.py --pattern "tiered-packaging"
655    python3 pricing_pattern_library.py --scenario "prospect is a $50M SaaS company spending $15K/mo on marketing"
656    python3 pricing_pattern_library.py --quiz
657          """,
658      )
659      parser.add_argument("--list", action="store_true", help="List all patterns with descriptions")
660      parser.add_argument("--pattern", help="Get detailed breakdown of a specific pattern")
661      parser.add_argument("--scenario", help="Analyze a scenario and recommend patterns")
662      parser.add_argument("--quiz", action="store_true", help="Interactive training mode")
663      parser.add_argument("--format", choices=["markdown", "json"], default="markdown", help="Output format (default: markdown)")
664  
665      args = parser.parse_args()
666  
667      if not any([args.list, args.pattern, args.scenario, args.quiz]):
668          parser.print_help()
669          sys.exit(0)
670  
671      if args.quiz:
672          run_quiz()
673          return
674  
675      if args.list:
676          if args.format == "json":
677              output = {k: {"name": v["name"], "tagline": v["tagline"], "when_to_use": v["when_to_use"][0]} for k, v in PATTERNS.items()}
678              print(json.dumps(output, indent=2))
679          else:
680              print(list_patterns())
681  
682      elif args.pattern:
683          if args.format == "json":
684              key = args.pattern.lower().replace(" ", "-").replace("_", "-")
685              if key in PATTERNS:
686                  print(json.dumps(PATTERNS[key], indent=2))
687              else:
688                  matches = [k for k in PATTERNS if key in k]
689                  if matches:
690                      print(json.dumps(PATTERNS[matches[0]], indent=2))
691                  else:
692                      print(json.dumps({"error": f"Pattern not found: {args.pattern}"}))
693          else:
694              print(get_pattern(args.pattern))
695  
696      elif args.scenario:
697          if args.format == "json":
698              # For JSON, just return the pattern recommendations
699              scenario_lower = args.scenario.lower()
700              keywords_map = {
701                  "anchor-with-data": ["data", "first call", "discovery", "competitive"],
702                  "tiered-packaging": ["budget", "price", "options", "tiers"],
703                  "competitive-ego-trigger": ["competitor", "behind", "losing", "ceo"],
704                  "strategic-involvement-upsell": ["expand", "more", "grow", "strategy"],
705                  "bridge-offer": ["in-house", "hire", "internal", "build"],
706                  "performance-skin-in-game": ["risk", "burned", "skeptic", "prove"],
707                  "value-math-on-screen": ["roi", "results", "numbers", "value"],
708                  "compound-effect-close": ["just seo", "single", "only", "one service"],
709                  "reference-customer-drop": ["proof", "show me", "example", "case study"],
710                  "in-house-team-framing": ["expensive", "cheaper", "agency", "compare"],
711              }
712              scored = []
713              for key, keywords in keywords_map.items():
714                  score = sum(1 for kw in keywords if kw in scenario_lower)
715                  if score > 0:
716                      scored.append({"pattern": key, "name": PATTERNS[key]["name"], "relevance_score": score})
717              scored.sort(key=lambda x: x["relevance_score"], reverse=True)
718              print(json.dumps({"scenario": args.scenario, "recommended_patterns": scored[:3]}, indent=2))
719          else:
720              print(analyze_scenario(args.scenario))
721  
722  
723  if __name__ == "__main__":
724      main()