{
  "schema_version": 1,
  "method_id": "ppcio-search-console-opportunity",
  "method_version": "1.2.0",
  "updated": "2026-08-01",
  "title": "Search Console Opportunity Method",
  "public_name": "Search Console Opportunity Pack",
  "promise": "Start with one product or service that already makes money, then turn closely related searches into a clear list of what to keep, fix, build, test in Google Ads, and ignore.",
  "public_safety": {
    "classification": "public",
    "contains_private_query_corpus": false,
    "contains_internal_economics": false,
    "contains_internal_queues": false,
    "contains_repository_or_deployment_details": false,
    "notes": "This method contains reusable rules. The companion worked example contains five exact query phrases observed in PPC.io Search Console. All example metrics, URLs, economics, dates, forecasts, page states, result-page observations, and test results are teaching inputs. It does not reproduce PPC.io's private dashboard data."
  },
  "audience": {
    "primary": [
      "PPC managers",
      "agency owners",
      "in-house marketers",
      "SEO practitioners"
    ],
    "assumed_knowledge": [
      "keywords",
      "landing pages",
      "clicks",
      "conversions"
    ],
    "not_required": [
      "Python",
      "an API token",
      "a data warehouse",
      "a keyword-difficulty subscription",
      "CTR modelling"
    ]
  },
  "profit_first": {
    "principle": "Keyword research starts with profit.",
    "workflow": [
      "Choose one product or service that already makes money",
      "Record plain-English proof such as completed sales, retained clients, qualified leads, or positive contribution",
      "Review searches closely related to that offer before adjacent topics",
      "Keep commercially relevant searches even when their volume is small",
      "Ignore high-volume distractions until the profitable theme is working"
    ],
    "rules": [
      "The business proves the offer; a keyword, competitor ad, or commercial-sounding phrase does not prove profit",
      "Do not require private revenue or margin figures when simpler business evidence identifies the proven offer",
      "Ignore for this pass is a sequencing decision, not a claim that the search can never be useful",
      "Protected brand demand or an existing page already doing its job can be Keep without entering the active investment queue",
      "Run a separate pass when another proven product or service is ready for focus"
    ]
  },
  "finish_line": {
    "quick_scan_target": "about 10 minutes",
    "finish_by_minutes": 15,
    "outcomes": [
      "One proven profitable product or service chosen as the focus",
      "A plain-English health check on the supplied data",
      "Ten reviewable search classifications",
      "At least one defensible SEO or PPC action",
      "A list of assumptions and unknowns",
      "A measurement row with a check date"
    ]
  },
  "decisions": [
    {
      "code": "KEEP",
      "label": "Keep",
      "plain_question": "Is this already bringing the right people to a useful page?",
      "use_when": [
        "The query reaches the intended page",
        "The audience is relevant",
        "The page already earns useful clicks or conversions",
        "A proposed change has no evidence-backed upside"
      ],
      "next_actions": [
        "Protect the page and its internal links",
        "Record the current baseline",
        "Avoid speculative title or body changes",
        "If paid and organic overlap matters, measure incrementality instead of assuming it"
      ]
    },
    {
      "code": "FIX",
      "label": "Fix",
      "plain_question": "Is the right opportunity reaching the wrong page, weak message, or broken conversion path?",
      "use_when": [
        "Google sends the query to the wrong page",
        "The intended page is losing rank",
        "Position is stable but the click appeal is weak",
        "The page is stale, thin, or built around the wrong thesis",
        "A paid click has nowhere useful to convert"
      ],
      "next_actions": [
        "Choose one fix type: Route, Retitle, Refresh, Re-angle, or Repair destination",
        "Change one class of thing at a time where attribution matters",
        "Write a baseline, prediction, falsifier, and check date before shipping"
      ]
    },
    {
      "code": "BUILD",
      "label": "Build",
      "plain_question": "Does real demand need a page that no suitable existing page should own?",
      "use_when": [
        "The query is closely related to the chosen profitable product or service",
        "The audience is relevant",
        "Observed or external demand exists",
        "No existing page should own the intent",
        "The live results page supports the proposed format",
        "The new page has a specific angle that current results do not deliver"
      ],
      "next_actions": [
        "Complete page-ownership and cannibalisation checks",
        "Inspect the live search results",
        "Write the unique-angle sentence",
        "Define the conversion path",
        "Set the new-page baseline and first check date"
      ]
    },
    {
      "code": "TEST_PPC",
      "label": "Test PPC",
      "plain_question": "Can a useful paid click be tested inside honest economics and a hard limit?",
      "use_when": [
        "The query is closely related to the chosen profitable product or service",
        "The audience is relevant",
        "A credible destination and conversion action exist",
        "Allowable cost per conversion and expected conversion rate are supplied",
        "A maximum CPC can be calculated",
        "The comparison uses the intended market",
        "A hard cap and stop rule are written before launch"
      ],
      "next_actions": [
        "Calculate maximum CPC",
        "Label allowable CPA and conversion rate as measured or assumed",
        "Price the intended market or use a capped discovery test",
        "Run a short, isolated test",
        "Replace assumptions with account evidence"
      ]
    },
    {
      "code": "IGNORE",
      "label": "Ignore",
      "plain_question": "Is this outside the current profitable theme, the wrong audience, a bad economic fit, or evidence that cannot support action?",
      "use_when": [
        "The searcher is not a plausible customer",
        "The query is a high-volume distraction outside the chosen profitable theme for this pass",
        "The low end of a market-labelled CPC forecast exceeds the maximum CPC",
        "The query has no strategic role after human review",
        "The apparent opportunity is a reporting artefact"
      ],
      "not_when": [
        "A closely related commercial search has low volume",
        "A value is merely missing",
        "A CPC or volume source returned no figure",
        "The user has not yet judged the audience"
      ],
      "next_actions": [
        "Record why it was rejected",
        "Keep it out of opportunity totals",
        "Revisit in a separate pass for another proven offer, or if the audience, offer, destination, or economics change"
      ]
    }
  ],
  "decision_statuses": [
    {
      "code": "READY",
      "meaning": "The decision has enough evidence and human judgement to act on."
    },
    {
      "code": "NEEDS_HUMAN",
      "meaning": "The data is present, but audience, offer, destination, or strategic ownership needs a person."
    },
    {
      "code": "BLOCKED_BY_DATA",
      "meaning": "A required input is missing. Keep the unknown visible rather than inventing a value."
    }
  ],
  "evidence_labels": [
    {
      "code": "OBSERVED",
      "label": "Observed",
      "meaning": "Directly present in the supplied source data."
    },
    {
      "code": "MEASURED",
      "label": "Measured",
      "meaning": "Learned from a real account result or controlled test."
    },
    {
      "code": "ESTIMATED",
      "label": "Estimated",
      "meaning": "A sourced forecast or transparent calculation."
    },
    {
      "code": "ASSUMED",
      "label": "Assumed",
      "meaning": "An input supplied by a person or agent that has not been measured."
    },
    {
      "code": "HUMAN_JUDGEMENT",
      "label": "Human judgement",
      "meaning": "An audience, offer, destination, or strategic choice that data cannot make alone."
    },
    {
      "code": "UNKNOWN",
      "label": "Unknown",
      "meaning": "Not known yet. It must not be represented as zero."
    }
  ],
  "missing_data_states": [
    {
      "code": "NOT_REQUESTED",
      "label": "Not requested",
      "meaning": "The source was never asked for the figure."
    },
    {
      "code": "UNAVAILABLE",
      "label": "Unavailable",
      "meaning": "The source was asked but did not disclose the figure."
    },
    {
      "code": "NOT_APPLICABLE",
      "label": "Not applicable",
      "meaning": "The field does not apply to this decision."
    }
  ],
  "input_modes": {
    "quick_scan": {
      "label": "Quick Scan",
      "required": [
        "A standard Search Console Queries export",
        "One product or service that already makes money and plain-English proof",
        "A short description of the customer for that offer",
        "Primary market",
        "One important conversion action"
      ],
      "limitations": [
        "A standard export may contain no page column",
        "The interface export is limited to representative rows",
        "Anonymised queries are omitted",
        "Page ownership and named-query coverage may remain unknown"
      ]
    },
    "full_plan": {
      "label": "Full Plan",
      "required": [
        "Query plus page Search Console rows",
        "Two matched date windows for page-change diagnosis",
        "One product or service that already makes money and plain-English proof",
        "Business, offer, destination, and conversion context"
      ],
      "optional": [
        "Google Ads keyword or search-term data",
        "Market-labelled Keyword Planner forecasts",
        "Measured allowable costs per conversion and conversion rates"
      ]
    }
  },
  "data_health": {
    "required_report": [
      "date range",
      "search type",
      "market scope",
      "device scope",
      "row count",
      "columns present",
      "files supplied",
      "named-query coverage when calculable",
      "limitations"
    ],
    "coverage_formula": "named query clicks divided by property total clicks for the same date, search type, market, and device scope",
    "coverage_rules": [
      "Do not calculate coverage from unmatched scopes",
      "Do not describe row count as coverage",
      "If the property total is absent, report coverage as Unknown",
      "Explain that anonymised and truncated queries can keep coverage below 100 percent"
    ],
    "position_rules": [
      "Judge each query at its query-level position",
      "Treat a page-average position as a mixed diagnostic, never as the page's rank",
      "Do not fold jump-link or fragment rows into impression totals without an explicit, justified aggregation rule"
    ],
    "official_sources": [
      {
        "label": "Google: export data directly from a Search Console report",
        "url": "https://support.google.com/webmasters/answer/12919797"
      },
      {
        "label": "Google: Performance report dimensions and data groupings",
        "url": "https://support.google.com/webmasters/answer/17011259"
      },
      {
        "label": "Google: Performance report data aggregation",
        "url": "https://support.google.com/webmasters/answer/17011364"
      }
    ]
  },
  "human_review": {
    "required_fields": [
      "Is this closely related to the chosen profitable product or service?",
      "Who searched?",
      "What did they want?",
      "Are they a plausible customer?",
      "What can we credibly offer?",
      "Where should the click land?",
      "What useful action can happen there?",
      "Why was this classification chosen?",
      "Has a person confirmed it?"
    ],
    "rules": [
      "Review the profitable offer and its evidence before search volume",
      "Keep closely related commercial searches even when volume is small",
      "Mark unrelated high-volume distractions Ignore for this pass until the profitable theme is working",
      "Keyword words are clues, not final intent",
      "Review ten rows before processing the full file",
      "Carry disagreements into the final output",
      "Do not generalise a person's correction to unrelated queries without review"
    ]
  },
  "organic_states": [
    {
      "code": "OWNED",
      "meaning": "The intended page already performs and should be protected."
    },
    {
      "code": "UNKNOWN_DEMAND",
      "meaning": "Real demand appears, but nobody deliberately mapped it to a page."
    },
    {
      "code": "MISPLACED",
      "meaning": "Google sends the search to the wrong page."
    },
    {
      "code": "LOSING",
      "meaning": "The intended page is present but losing rank or clicks."
    },
    {
      "code": "WRONG_AUDIENCE",
      "meaning": "The search is real, but the person behind it is not commercially relevant."
    }
  ],
  "seo_actions": [
    {
      "code": "PROTECT",
      "use_when": "The intended page is already working."
    },
    {
      "code": "ROUTE",
      "use_when": "The query reaches the wrong page."
    },
    {
      "code": "RETITLE",
      "use_when": "Query-level position is stable and click appeal is the isolated problem."
    },
    {
      "code": "REFRESH",
      "use_when": "The page thesis remains correct but the evidence, depth, or usefulness has aged."
    },
    {
      "code": "RE_ANGLE",
      "use_when": "Rank is falling, the thesis is wrong, or a platform now owns the basic answer."
    },
    {
      "code": "WRITE",
      "use_when": "No suitable page owns a distinct, proven intent and the Build gates pass."
    },
    {
      "code": "MERGE",
      "use_when": "Two pages compete for one intent and one should absorb the other."
    }
  ],
  "matched_window_teaching_example": {
    "inputs_note": "These two matched-window rows are entirely fictional teaching data. They are separate from the five real query phrases in the worked example and are not PPC.io actuals.",
    "rows": [
      {
        "lesson": "Rank loss",
        "page": "https://example.test/guides/ppc-audit",
        "query": "ppc audit checklist",
        "previous_window": "2026-04-01 to 2026-04-28",
        "current_window": "2026-04-29 to 2026-05-26",
        "previous_position": 4.2,
        "current_position": 8.7,
        "previous_impressions": 2000,
        "current_impressions": 1800,
        "previous_clicks": 160,
        "current_clicks": 72,
        "previous_ctr": "8.0%",
        "current_ctr": "4.0%",
        "diagnosis": "Position fell materially, so the click loss cannot be isolated as a title problem.",
        "action": "Diagnose the rank loss, then Refresh or Re-angle if the evidence supports it. Do not start with Retitle."
      },
      {
        "lesson": "Click loss at stable rank",
        "page": "https://example.test/guides/google-ads-audit-template",
        "query": "google ads audit template",
        "previous_window": "2026-04-01 to 2026-04-28",
        "current_window": "2026-04-29 to 2026-05-26",
        "previous_position": 3.2,
        "current_position": 3.3,
        "previous_impressions": 2000,
        "current_impressions": 2000,
        "previous_clicks": 190,
        "current_clicks": 118,
        "previous_ctr": "9.5%",
        "current_ctr": "5.9%",
        "diagnosis": "Position and impressions stayed stable while clicks fell, so click appeal is the isolated candidate.",
        "action": "Run a title and snippet test with the body unchanged, then read it on 2026-06-16."
      }
    ]
  },
  "ppc_economics": {
    "formula": "maximum CPC = allowable cost per conversion x expected conversion rate",
    "lead_business_formula": "allowable cost per lead = gross contribution per sale x lead-to-sale close rate x (1 - required margin retained)",
    "lead_business_explanation": "First estimate the gross contribution or value created by one sale. Multiply it by the proportion of leads that become sales. Then reserve the required share of that expected contribution as margin. What remains is the allowable cost for one lead conversion.",
    "required_fields": [
      "allowable cost per conversion",
      "allowable CPA basis",
      "expected conversion rate",
      "evidence label for allowable CPA",
      "evidence label for conversion rate",
      "maximum CPC",
      "market",
      "market CPC source and date",
      "destination",
      "conversion action",
      "hard cap",
      "stop rule"
    ],
    "rules": [
      "Calculate the ceiling before looking at a CPC forecast",
      "For a lead business, derive allowable CPA from lead-to-sale close rate, gross contribution or value per sale, and the required margin to retain",
      "Use the same currency throughout one row",
      "A missing bid figure is Unknown, Not requested, or Unavailable, never zero",
      "A forecast describes an auction estimate, not demand you can capture",
      "If the destination cannot convert, choose Fix before Test PPC",
      "If the low forecast exceeds the maximum CPC, choose Ignore for that market",
      "If no forecast is available and every other gate passes, use a small capped discovery test",
      "Never mutate a live campaign or budget automatically"
    ]
  },
  "build_gate": {
    "required_questions": [
      "Which existing pages overlap this intent?",
      "Should one of those pages be reworked or merged instead?",
      "What proves demand exists?",
      "What format dominates the live results page?",
      "Are AI Overviews, community results, video, or product surfaces present?",
      "What will this page do that no current result does?",
      "Where will the visitor go next?"
    ],
    "allowed_verdicts": [
      "WRITE NEW",
      "MERGE",
      "REWORK INSTEAD"
    ],
    "invalid_differentiation": [
      "more comprehensive",
      "better structured",
      "more up to date"
    ]
  },
  "measurement": {
    "required_fields": [
      "change",
      "URL or keyword",
      "baseline window",
      "comparison window",
      "expected direction",
      "the result that would prove the idea wrong",
      "first readable date",
      "result",
      "confounder",
      "what changes in the method"
    ],
    "result_values": [
      "HIT",
      "MISS",
      "INCONCLUSIVE"
    ],
    "rules": [
      "Write the prediction before the result exists",
      "Compare windows of equal length and equivalent scope",
      "Separate rank movement from click-rate movement",
      "Name the confounder when the result is inconclusive",
      "Record misses because they are the evidence that changes the method",
      "Write a real ISO date before shipping or launching; never leave First readable date as a duration or placeholder",
      "Score SEO only after the full comparison window ends and Search Console contains that window",
      "Score PPC on the later of the planned test end and the written minimum evidence threshold; if the threshold is still unmet, mark Inconclusive rather than extending until a win"
    ],
    "first_readable_date_rules": {
      "title_or_snippet_change": "Use the change date plus 21 calendar days. Example: a change live on 2026-08-03 is first read on 2026-08-24.",
      "ranking_or_page_change": "Use the live date plus 56 calendar days. Example: a page live on 2026-08-03 is first read on 2026-09-28.",
      "capped_ppc_test": "Use the day after the planned test ends, but read only if the written click, spend, or conversion threshold was reached. Example: a test ending 2026-08-16 is first read on 2026-08-17. If the threshold is not reached, score Inconclusive."
    },
    "typical_first_read": {
      "title_or_snippet_change": "2 to 3 weeks",
      "ranking_or_page_change": "6 to 12 weeks",
      "capped_ppc_test": "about 2 weeks, subject to enough traffic and conversion volume"
    }
  },
  "agent_contract": {
    "business_question_limit": 5,
    "canary_rows": 10,
    "conversation_order": [
      "Choose one proven profitable product or service, then export the Search Console rows",
      "Run the agent with the export",
      "Answer five business questions",
      "Correct ten rows with the user after showing the canary",
      "Generate the five-decision board after those corrections",
      "Record one chosen action in the workbook and 91-day tracker"
    ],
    "output_order": [
      "Data health",
      "Top three findings",
      "Keep / Fix / Build / Test PPC / Ignore board",
      "SEO queue",
      "PPC test queue",
      "Human decisions still needed",
      "Assumptions and unknowns",
      "91-day measurement rows"
    ]
  },
  "workbook_contract": {
    "tabs": [
      {
        "name": "Start Here",
        "purpose": "Choose one proven profitable offer, record the evidence that it already makes money, define the analysis scope, and show the current step.",
        "primary_owner": "Human",
        "handoff": "Name one product or service already making money, record the plain-English proof, choose the route, enter the scope, and follow the six numbered steps. No rows move between tabs automatically.",
        "fields": [
          "Business or site",
          "Profitable offer for this pass",
          "Proof it already makes money",
          "Analysis date",
          "Search Console start date",
          "Search Console end date",
          "Search type",
          "Primary market",
          "Device scope",
          "Route",
          "Files supplied",
          "Named query clicks",
          "Matching property total clicks",
          "Named-query coverage",
          "Last refresh",
          "Current step"
        ]
      },
      {
        "name": "Raw Search Console",
        "purpose": "Keep the supplied rows unchanged before adding judgement.",
        "primary_owner": "Human",
        "handoff": "Paste or import the source export here as untrusted data. Format Query as text and preserve the original values.",
        "columns": [
          "Query",
          "Page",
          "Clicks",
          "Impressions",
          "CTR",
          "Query position",
          "Country",
          "Device",
          "Window start",
          "Window end",
          "Search type",
          "Source",
          "Duplicate or jump-link status"
        ]
      },
      {
        "name": "Offers",
        "purpose": "Define what a useful click can do before looking at CPC.",
        "primary_owner": "Human",
        "handoff": "Enter and approve the offer, working action, allowable CPA, and evidence. The agent may draft, but must not invent these inputs.",
        "columns": [
          "Offer name",
          "Intended buyer",
          "Destination",
          "Conversion action",
          "Action works",
          "Currency",
          "Allowable cost per conversion",
          "Allowable CPA basis",
          "Expected conversion rate",
          "CPA evidence",
          "Rate evidence",
          "Evidence date",
          "Maximum CPC",
          "Notes"
        ]
      },
      {
        "name": "Intent Ledger",
        "purpose": "Make audience, offer, and destination judgements visible and correctable.",
        "primary_owner": "Agent drafts, human confirms",
        "handoff": "Paste the agent's ten-row canary here or transfer the corrected rows manually, then confirm the audience, offer, and destination.",
        "columns": [
          "Exact query",
          "Who searched",
          "What they wanted",
          "Audience class",
          "Right audience",
          "What can be offered",
          "Current landing page",
          "Intended landing page",
          "Conversion action",
          "Reason for classification",
          "Human confirmed",
          "Confidence",
          "Review date",
          "Evidence status"
        ]
      },
      {
        "name": "Opportunity Board",
        "purpose": "Turn reviewed searches into five decisions, with closely related profit-theme searches first.",
        "primary_owner": "Agent drafts, human chooses",
        "handoff": "Paste the board returned after the ten-row correction, or transfer chosen rows manually. Keep low-volume searches when they closely match the profitable offer, ignore high-volume distractions for this pass, and select one action to carry forward.",
        "columns": [
          "Query or theme",
          "Observed demand",
          "Current page",
          "Decision",
          "Decision status",
          "Reason",
          "Evidence status",
          "Missing information",
          "Priority",
          "Owner",
          "Next action"
        ]
      },
      {
        "name": "SEO Queue",
        "purpose": "Separate page diagnosis from the paid decision.",
        "primary_owner": "Agent drafts, human approves",
        "handoff": "Manually copy an approved Fix, Build, or Keep action here unless the agent has pasted it. Verify every ownership and live-results claim.",
        "columns": [
          "Current page",
          "Primary query",
          "Current window",
          "Previous matched window",
          "Rank movement",
          "Click movement",
          "Stable position",
          "Existing-page action",
          "Overlapping pages",
          "New-page verdict",
          "SERP format",
          "AI Overview present",
          "Unique-angle sentence",
          "Required assets",
          "Baseline",
          "Prediction",
          "Result that proves it wrong",
          "Check date",
          "Evidence status",
          "Notes"
        ]
      },
      {
        "name": "PPC Test Queue",
        "purpose": "Price and limit paid tests without hiding assumptions.",
        "primary_owner": "Agent calculates, human approves",
        "handoff": "Manually copy an approved paid candidate here unless the agent has pasted it. A human owns the economics, cap, stop rule, and any launch.",
        "columns": [
          "Query or theme",
          "Audience",
          "Destination",
          "Conversion action",
          "Currency",
          "Allowable cost per conversion",
          "Allowable CPA basis",
          "CPA evidence",
          "Expected conversion rate",
          "Rate evidence",
          "Maximum CPC",
          "Market",
          "Forecast low CPC",
          "Forecast high CPC",
          "Forecast status",
          "Decision",
          "Hard cap",
          "Test duration",
          "Stop condition",
          "Actual CPC",
          "Actual conversions",
          "Actual conversion rate",
          "Final verdict",
          "Notes"
        ]
      },
      {
        "name": "91-Day Tracker",
        "purpose": "Write the prediction before the result exists and score it honestly.",
        "primary_owner": "Human",
        "handoff": "Manually record the one chosen action before it ships. Use a real first-readable date and score it only when that date and evidence threshold are reached.",
        "columns": [
          "Change",
          "URL or keyword",
          "Baseline window",
          "Comparison window",
          "Expected direction",
          "Result that proves the idea wrong",
          "First readable date",
          "Result",
          "Confounder",
          "What changes in the method",
          "Owner",
          "Notes"
        ]
      },
      {
        "name": "Glossary + Example",
        "purpose": "Keep plain-language definitions and the five worked decisions beside the template.",
        "primary_owner": "Reference",
        "handoff": "Read this tab when a field is unfamiliar. Do not paste working data here."
      }
    ]
  },
  "public_vocabulary": [
    {
      "prefer": "one product or service already making money",
      "avoid_on_first_use": "profit-theme constraint"
    },
    {
      "prefer": "the searches showing your site",
      "avoid_on_first_use": "query corpus"
    },
    {
      "prefer": "how much of your traffic has a named search",
      "avoid_on_first_use": "query-slice coverage"
    },
    {
      "prefer": "the most you can pay for one click",
      "avoid_on_first_use": "maximum CPC"
    },
    {
      "prefer": "the result that would prove the idea wrong",
      "avoid_on_first_use": "falsifier"
    },
    {
      "prefer": "pages competing for the same search",
      "avoid_on_first_use": "cannibalisation"
    },
    {
      "prefer": "two date ranges of the same length",
      "avoid_on_first_use": "matched windows"
    },
    {
      "prefer": "right person, useful page, honest price",
      "avoid_on_first_use": "cross-channel arbitrage"
    }
  ],
  "retired_claims": [
    {
      "id": "volume-first-priority",
      "retired": "The keywords with the highest search volume should be prioritised first.",
      "regression_example": "Prioritise the keywords with the highest search volume first.",
      "replacement": "Start with one proven profitable product or service. Keep closely related searches even when volume is small, and ignore unrelated volume until that theme is working.",
      "forbidden_patterns": [
        "prioriti[sz]e (the )?keywords? with the highest (search )?volume first",
        "sort by (highest|largest) (search )?volume and start"
      ]
    },
    {
      "id": "page-average-is-rank",
      "retired": "Page-average position can be used as the page's rank.",
      "regression_example": "Use page-average position to rank the opportunities.",
      "replacement": "Judge each search at its own query-level position.",
      "forbidden_patterns": [
        "page[- ]average position (is|equals|means) (the )?(page'?s )?rank",
        "use page[- ]average position to (rank|prioriti[sz]e|score)"
      ]
    },
    {
      "id": "universal-ctr-curve",
      "retired": "One CTR-by-rank table can estimate clicks for every site and results page.",
      "regression_example": "Expected CTR at position 1 is 30%.",
      "replacement": "Use site-derived, query-level evidence when it is thick enough. Otherwise say the benchmark is unknown.",
      "forbidden_patterns": [
        "(?:expected )?ctr (?:at|for) position 1[^\\n]{0,40}(28|30|32)%",
        "universal ctr (curve|table)",
        "expected ctr.*position 1.*%"
      ]
    },
    {
      "id": "modifier-intent",
      "retired": "Words such as buy, best, review, or how are enough to decide buyer intent.",
      "regression_example": "Use an intent multiplier to value commercial searches.",
      "replacement": "Treat keyword words as clues and require a reviewable human judgement.",
      "forbidden_patterns": [
        "intent multiplier",
        "transactional modifiers?[^\\n]{0,80}(include|high intent)",
        "commercial modifiers?[^\\n]{0,80}(include|high intent)"
      ]
    },
    {
      "id": "difficulty-timeline",
      "retired": "Keyword difficulty maps to a fixed number of months to rank.",
      "regression_example": "Keyword difficulty 30 means 3-6 months to rank.",
      "replacement": "Use the current page, results page, authority, and test evidence. Do not promise a ranking date from a difficulty score.",
      "forbidden_patterns": [
        "keyword difficulty[^\\n]{0,100}(1-3|3-6|6-12|9-18) months",
        "kd ?[<=>].*months"
      ]
    },
    {
      "id": "default-incrementality",
      "retired": "Paid clicks are 70 percent incremental by default.",
      "regression_example": "Use a default 70% incrementality assumption.",
      "replacement": "Measure overlap with a controlled test where justified, or label the incrementality assumption explicitly.",
      "forbidden_patterns": [
        "default[^\\n]{0,30}70%[^\\n]{0,40}incrementality",
        "incrementality adjustment[^\\n]{0,30}0\\.70"
      ]
    },
    {
      "id": "money-on-table",
      "retired": "A generic multiplier can produce a defensible money-on-the-table total.",
      "regression_example": "There is £50,000 money left on the table.",
      "replacement": "Show the inputs and label the output as an estimate or ceiling, never measured revenue.",
      "forbidden_patterns": [
        "money (left|trapped) on the table",
        "guaranteed (savings|revenue|value)"
      ]
    },
    {
      "id": "missing-is-zero",
      "retired": "Missing CPC, volume, conversions, or benchmark data equals zero.",
      "regression_example": "Treat missing CPC as zero.",
      "replacement": "Use Unknown, Not requested, Unavailable, or Not applicable.",
      "forbidden_patterns": [
        "missing (cpc|volume|conversions?|benchmark)[^\\n]{0,30}(=|as) (0|zero)",
        "no (cpc|volume) data[^\\n]{0,30}(means|=) no (demand|opportunity)"
      ]
    },
    {
      "id": "same-source-corroboration",
      "retired": "Keyword Planner and a reseller of Google keyword data are independent corroboration.",
      "regression_example": "DataForSEO is an independent source beside Keyword Planner.",
      "replacement": "Name the upstream source and do not count the same source twice.",
      "forbidden_patterns": [
        "dataforseo[^\\n]{0,80}independent (source|corroboration|validation)",
        "keyword planner[^\\n]{0,80}dataforseo[^\\n]{0,80}two independent"
      ]
    },
    {
      "id": "competitor-profit-proof",
      "retired": "A competitor advertising on a keyword proves that keyword is profitable.",
      "regression_example": "Competitors are bidding, so this keyword is profitable.",
      "replacement": "Competitor activity proves only that an ad was observed. Your account must prove economics.",
      "forbidden_patterns": [
        "competitor[^\\n]{0,60}(advertis|bid)[^\\n]{0,60}proves? profit",
        "competitors? are bidding[^\\n]{0,50}profitable"
      ]
    },
    {
      "id": "gsc-silence-build",
      "retired": "No Search Console coverage means a new page should be built.",
      "regression_example": "No Search Console impressions means create a new page.",
      "replacement": "Check existing page ownership and external demand before Build.",
      "forbidden_patterns": [
        "no (gsc|search console) (coverage|impressions|query)[^\\n]{0,80}(build|create) (a )?new page",
        "no organic coverage[^\\n]{0,80}create seo page"
      ]
    },
    {
      "id": "retitle-decliner",
      "retired": "A weak click rate justifies a title change even while rank is falling.",
      "regression_example": "Position is falling, so retitle the page.",
      "replacement": "Use Retitle only when query-level position is stable and click appeal is isolated.",
      "forbidden_patterns": [
        "position is (falling|declining)[^\\n]{0,80}retitle",
        "retitle[^\\n]{0,80}while (rank|position) is (falling|declining)"
      ]
    },
    {
      "id": "mixed-market",
      "retired": "Worldwide volume can be compared with an unlabelled local CPC.",
      "regression_example": "Compare worldwide volume with UK CPC.",
      "replacement": "Label the market and currency on every CPC or volume forecast.",
      "forbidden_patterns": [
        "(?<!do not compare )worldwide volume[^\\n]{0,80}(local|uk|us) cpc",
        "global volume[^\\n]{0,80}unlabelled cpc"
      ]
    },
    {
      "id": "forecast-is-capturable",
      "retired": "A forecast is traffic or revenue the business can capture.",
      "regression_example": "The forecast is guaranteed traffic.",
      "replacement": "A forecast is an estimate to compare with a cap, not a promise.",
      "forbidden_patterns": [
        "forecast[^\\n]{0,50}capturable demand",
        "forecast[^\\n]{0,50}guaranteed (traffic|clicks|revenue)"
      ]
    }
  ]
}
