taketomarket 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +4 -4
- package/.claude-plugin/plugin.json +2 -2
- package/README.md +34 -11
- package/bin/lib/campaign.cjs +12 -8
- package/bin/lib/codebase-scan.cjs +86 -0
- package/bin/lib/config.cjs +129 -0
- package/bin/lib/deploy.cjs +36 -0
- package/bin/lib/deviation.cjs +1 -1
- package/bin/lib/drift-log.cjs +4 -4
- package/bin/lib/health.cjs +32 -31
- package/bin/lib/install-detect.cjs +62 -0
- package/bin/lib/legacy-folder.cjs +100 -0
- package/bin/lib/playwright-check.cjs +26 -0
- package/bin/lib/site-location.cjs +22 -0
- package/bin/lib/state.cjs +3 -3
- package/bin/lib/svg-render.cjs +42 -0
- package/bin/ttm-tools.cjs +136 -4
- package/gates/base-gates.md +8 -8
- package/gates/gate-evaluation.md +8 -8
- package/install.js +37 -3
- package/package.json +10 -6
- package/playbooks/aeo.md +218 -114
- package/playbooks/affiliate.md +225 -160
- package/playbooks/email.md +236 -174
- package/playbooks/events.md +303 -213
- package/playbooks/landing-pages.md +305 -0
- package/playbooks/linkedin.md +264 -142
- package/playbooks/manifesto.md +322 -0
- package/playbooks/paid-ads.md +240 -189
- package/playbooks/positioning.md +340 -0
- package/playbooks/pr-media.md +308 -168
- package/playbooks/pseo.md +426 -0
- package/playbooks/seo.md +251 -158
- package/playbooks/social.md +253 -182
- package/playbooks/youtube.md +286 -181
- package/references/brand-color-theory.md +48 -0
- package/references/codex-image-gen-research.md +58 -0
- package/references/context-loading.md +6 -6
- package/references/humanizer-patterns.md +433 -0
- package/references/inline-education-blurbs.md +461 -0
- package/references/landing-page-anatomy.md +64 -0
- package/references/linkedin-post-patterns.md +174 -0
- package/references/logo-design-principles.md +55 -0
- package/references/meta-gate-evaluation.md +3 -3
- package/references/obra-superpowers-conventions.md +170 -0
- package/references/playbook-leaders.md +472 -0
- package/references/playwright-mcp-setup.md +164 -0
- package/references/positioning-check-report.md +2 -2
- package/references/pseo-page-anatomy.md +56 -0
- package/references/pseo-templates/alternative-anatomy.md +31 -0
- package/references/pseo-templates/alternative-content-playbook.md +32 -0
- package/references/pseo-templates/blog-anatomy.md +28 -0
- package/references/pseo-templates/blog-content-playbook.md +36 -0
- package/references/pseo-templates/comparison-anatomy.md +29 -0
- package/references/pseo-templates/comparison-content-playbook.md +35 -0
- package/references/pseo-templates/use-case-anatomy.md +28 -0
- package/references/pseo-templates/use-case-content-playbook.md +30 -0
- package/skills/ttm-101/SKILL.md +25 -0
- package/skills/ttm-aeo-check/SKILL.md +17 -12
- package/skills/ttm-affiliate-kit/SKILL.md +5 -0
- package/skills/ttm-archive/SKILL.md +5 -0
- package/skills/ttm-brand-refresh/SKILL.md +5 -0
- package/skills/ttm-brief/SKILL.md +5 -0
- package/skills/ttm-competitor-scan/SKILL.md +5 -0
- package/skills/ttm-deploy/SKILL.md +22 -0
- package/skills/ttm-discover/SKILL.md +17 -0
- package/skills/ttm-email-check/SKILL.md +17 -0
- package/skills/ttm-email-preflight/SKILL.md +17 -11
- package/skills/ttm-fix/SKILL.md +5 -0
- package/skills/ttm-health/SKILL.md +6 -1
- package/skills/ttm-humanize/SKILL.md +33 -0
- package/skills/ttm-icp-refresh/SKILL.md +5 -0
- package/skills/ttm-improve-skill/SKILL.md +18 -0
- package/skills/ttm-init/SKILL.md +10 -3
- package/skills/ttm-keyword-map/SKILL.md +17 -11
- package/skills/ttm-landing/SKILL.md +19 -0
- package/skills/ttm-learn/SKILL.md +5 -0
- package/skills/ttm-linkedin-post/SKILL.md +26 -0
- package/skills/ttm-measure/SKILL.md +5 -0
- package/skills/ttm-new-campaign/SKILL.md +5 -0
- package/skills/ttm-next/SKILL.md +5 -0
- package/skills/ttm-playwright-setup/SKILL.md +18 -0
- package/skills/ttm-positioning-check/SKILL.md +5 -0
- package/skills/ttm-positioning-shift/SKILL.md +5 -0
- package/skills/ttm-produce/SKILL.md +5 -0
- package/skills/ttm-pseo/SKILL.md +26 -0
- package/skills/ttm-repurpose/SKILL.md +5 -0
- package/skills/ttm-request-skill/SKILL.md +18 -0
- package/skills/ttm-research/SKILL.md +18 -6
- package/skills/ttm-resume/SKILL.md +5 -0
- package/skills/ttm-review/SKILL.md +5 -0
- package/skills/ttm-seo/SKILL.md +64 -0
- package/skills/ttm-seo-audit/SKILL.md +17 -12
- package/skills/ttm-ship/SKILL.md +5 -0
- package/skills/ttm-state/SKILL.md +5 -0
- package/skills/ttm-update/SKILL.md +152 -4
- package/skills/ttm-verify/SKILL.md +5 -0
- package/templates/agents-md.md +14 -4
- package/templates/campaign-research.md +6 -6
- package/templates/campaign-state.md +1 -1
- package/templates/claude-md.md +14 -4
- package/templates/linkedin-base-template.md +48 -0
- package/templates/next-step-footer.md +13 -0
- package/templates/production-manifest.json +4 -4
- package/templates/pseo/alternative-cms-schema.json +65 -0
- package/templates/pseo/blog-cms-schema.json +55 -0
- package/templates/pseo/comparison-cms-schema.json +56 -0
- package/templates/pseo/use-case-cms-schema.json +62 -0
- package/templates/reference-files/brand.md +51 -0
- package/templates/reference-files/product-dna.md +73 -0
- package/templates/site-scaffold/app/globals.css +2 -0
- package/templates/site-scaffold/app/layout.tsx +17 -0
- package/templates/site-scaffold/app/page.tsx +33 -0
- package/templates/site-scaffold/app/robots.ts +8 -0
- package/templates/site-scaffold/app/sitemap.ts +10 -0
- package/templates/site-scaffold/app/tokens.css +21 -0
- package/templates/site-scaffold/components/Comparison.tsx +14 -0
- package/templates/site-scaffold/components/Faq.tsx +14 -0
- package/templates/site-scaffold/components/Features.tsx +14 -0
- package/templates/site-scaffold/components/FinalCta.tsx +17 -0
- package/templates/site-scaffold/components/Footer.tsx +12 -0
- package/templates/site-scaffold/components/Hero.tsx +22 -0
- package/templates/site-scaffold/components/HowItWorks.tsx +14 -0
- package/templates/site-scaffold/components/PricingTeaser.tsx +14 -0
- package/templates/site-scaffold/components/Problem.tsx +14 -0
- package/templates/site-scaffold/components/SocialProof.tsx +14 -0
- package/templates/site-scaffold/components/Solution.tsx +14 -0
- package/templates/site-scaffold/components/Testimonials.tsx +14 -0
- package/templates/site-scaffold/components/UseCases.tsx +14 -0
- package/templates/site-scaffold/content/.gitkeep +0 -0
- package/templates/site-scaffold/lib/.gitkeep +0 -0
- package/templates/site-scaffold/next.config.mjs +10 -0
- package/templates/site-scaffold/package.json +25 -0
- package/templates/site-scaffold/postcss.config.mjs +3 -0
- package/templates/site-scaffold/public/llms.txt +9 -0
- package/templates/site-scaffold/tsconfig.json +21 -0
- package/templates/verification-report.md +1 -1
- package/workflows/channel/linkedin-post.md +178 -0
- package/workflows/discipline/affiliate-kit.md +65 -6
- package/workflows/discipline/{email-preflight.md → email-check.md} +39 -4
- package/workflows/discipline/repurpose.md +82 -31
- package/workflows/discipline/{aeo-check.md → seo/aeo.md} +13 -6
- package/workflows/discipline/{seo-audit.md → seo/audit.md} +13 -6
- package/workflows/discipline/{keyword-map.md → seo/keyword-map.md} +13 -6
- package/workflows/education/ttm-101.md +114 -0
- package/workflows/lifecycle/brief-positioning-check.md +1 -1
- package/workflows/lifecycle/brief.md +64 -28
- package/workflows/lifecycle/{research.md → discover.md} +61 -19
- package/workflows/lifecycle/fix.md +72 -37
- package/workflows/lifecycle/humanize.md +280 -0
- package/workflows/lifecycle/learn.md +72 -35
- package/workflows/lifecycle/measure.md +54 -18
- package/workflows/lifecycle/produce.md +88 -37
- package/workflows/lifecycle/review.md +71 -25
- package/workflows/lifecycle/ship.md +62 -18
- package/workflows/lifecycle/verify.md +72 -26
- package/workflows/reference-mgmt/brand-refresh.md +50 -13
- package/workflows/reference-mgmt/competitor-scan.md +51 -15
- package/workflows/reference-mgmt/icp-refresh.md +48 -12
- package/workflows/reference-mgmt/positioning-check.md +55 -20
- package/workflows/reference-mgmt/positioning-shift.md +53 -17
- package/workflows/setup/init-brand-colors.md +75 -0
- package/workflows/setup/init-logo.md +113 -0
- package/workflows/setup/init-product-dna.md +83 -0
- package/workflows/setup/init-questions.md +166 -30
- package/workflows/setup/init-validation.md +22 -0
- package/workflows/setup/init.md +144 -39
- package/workflows/setup/new-campaign.md +48 -12
- package/workflows/site/deploy.md +98 -0
- package/workflows/site/landing.md +156 -0
- package/workflows/site/pseo.md +96 -0
- package/workflows/site/quality-gates.md +88 -0
- package/workflows/utility/archive.md +45 -9
- package/workflows/utility/health.md +77 -3
- package/workflows/utility/improve-skill.md +233 -0
- package/workflows/utility/next.md +38 -2
- package/workflows/utility/playwright-setup.md +128 -0
- package/workflows/utility/request-skill.md +218 -0
- package/workflows/utility/resume.md +40 -3
- package/workflows/utility/state.md +42 -7
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
---
|
|
2
|
+
discipline: pseo
|
|
3
|
+
asset_types: [pseo-blog, pseo-use-case, pseo-comparison, pseo-alternative]
|
|
4
|
+
version: "1.0"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# pSEO Discipline Playbook
|
|
8
|
+
|
|
9
|
+
This playbook extends the base playbook contract (`base.md`) with programmatic-SEO production guidance, discipline gates, and format rules. It is loaded by ttm-producer during pSEO content generation and parsed by ttm-verify for gate evaluation.
|
|
10
|
+
|
|
11
|
+
The playbook is opinionated around **Practical Programmatic SEO** as taught by Ian Nuttall (Practical Programmatic, *No-Code Programmatic SEO*). Per-template page anatomy lives in `references/pseo-page-anatomy.md` (shared structure) and the four template-specific files in `references/pseo-templates/` — this playbook governs the **data × template × intent strategy layer** that decides whether a pSEO project should exist at all and when its pages are allowed to hit the index.
|
|
12
|
+
|
|
13
|
+
For the broader SEO measurement strategy this work plugs into, see `playbooks/seo.md` (Aleyda Solis's 3-Layer model). For passage-level citability of individual templated pages, see `playbooks/aeo.md` (Mike King's Relevance Engineering).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Production Guidance
|
|
18
|
+
|
|
19
|
+
### pSEO is data × template × intent — all three or none
|
|
20
|
+
|
|
21
|
+
A working pSEO page is the product of three inputs, multiplied. Miss any one and the project doesn't fail gracefully — it generates spam.
|
|
22
|
+
|
|
23
|
+
- **Data** — a structured source where every row is a real, distinct entity (cities, tools, languages, recipes, jobs, datasets, integrations). The rows are the unit of unique content. If the data source has 500 rows, that is the ceiling on the project. Don't pad rows with AI to get to 5,000.
|
|
24
|
+
- **Template** — a single, repeatable page shape that consistently presents the data for one row. One template. Tested before scale. Same layout, same H2 structure, same schema fields populated from the same column names. The template is code; the rows are inputs.
|
|
25
|
+
- **Intent** — a specific, observable thing the searcher wants when they land on this page. Not "they typed something with this row's name in it." A real job-to-be-done that the templated page completes. "Compare Tool A to Tool B for use case Y." "Find the cheapest flight from City X to City Y in November." "Convert Language X to Language Y."
|
|
26
|
+
|
|
27
|
+
If any one of the three is absent, the project is not pSEO — it is index pollution wearing a template costume.
|
|
28
|
+
|
|
29
|
+
### Find the data source first, not the template
|
|
30
|
+
|
|
31
|
+
Most failed pSEO projects start with a template idea — "let's make a page for every X" — and then go looking for data to fill it. That ordering is backwards and it is the single most common reason pSEO sites flame out at scale.
|
|
32
|
+
|
|
33
|
+
Reverse the order. Start with: **"What data do I already have that is uniquely useful, hard to assemble, and difficult for a competitor to replicate?"** The data source is the moat. The template is the delivery mechanism. A great template wrapped around weak data produces thin pages at scale; a mediocre template wrapped around a proprietary data set produces a defensible long tail.
|
|
34
|
+
|
|
35
|
+
Acceptable data sources, in rough order of defensibility:
|
|
36
|
+
|
|
37
|
+
1. **First-party data only you have** — your own usage stats, integrations, customer outcomes, pricing comparisons run against your own tool.
|
|
38
|
+
2. **Aggregated public data with non-trivial cleaning** — government datasets, public APIs, scrape + normalize + enrich.
|
|
39
|
+
3. **Permissioned third-party data** — licensed feeds, partner data, official APIs (Crunchbase, Stripe, etc.).
|
|
40
|
+
4. **AI-summarized public content** — last resort, and only when the summary genuinely outperforms the source in clarity or aggregation. Pure AI generation with no anchor data does not count as a data source.
|
|
41
|
+
|
|
42
|
+
### Template once; scale forever
|
|
43
|
+
|
|
44
|
+
Build one template. Ship one row populated by the template. Then ship ten. Read all ten as a human and ask: "If I landed on this page from a Google search, would I be satisfied?" Fix the template until the answer is yes for all ten. *Then* generate the next thousand.
|
|
45
|
+
|
|
46
|
+
Do not skip the test phase. Do not ship the template and the 10,000 pages on the same day. Every failed pSEO site shares the same origin story — they generated the long tail before the short tail had been pressure-tested.
|
|
47
|
+
|
|
48
|
+
### Two-axis pSEO patterns — pick one and commit
|
|
49
|
+
|
|
50
|
+
Almost every successful pSEO site fits one of two axis patterns:
|
|
51
|
+
|
|
52
|
+
- **[Thing] × [Location]** — "best [thing] in [city]", "[service] near [zipcode]", "things to do in [city] in [month]". The row dimension is geography; data needs to be locally specific.
|
|
53
|
+
- **[Thing] × [Thing]** — "[tool A] vs [tool B]", "[language X] to [language Y]", "[recipe] without [ingredient]", "alternatives to [thing]". The row dimension is pairwise comparison; data needs to be entity-specific for both sides.
|
|
54
|
+
|
|
55
|
+
Mixing axes ("best [thing] in [city] vs [other thing] in [other city]") explodes the row count, dilutes intent per page, and produces a long tail of zero-search-volume URLs. Pick one axis. The four asset types in this playbook map to specific axis patterns:
|
|
56
|
+
|
|
57
|
+
- `pseo-blog` — often single-axis content (informational templates).
|
|
58
|
+
- `pseo-use-case` — [thing] × [use case] axis.
|
|
59
|
+
- `pseo-comparison` — [thing] × [thing] axis (head-to-head).
|
|
60
|
+
- `pseo-alternative` — [thing] × [thing] axis (one-to-many, alternatives-to).
|
|
61
|
+
|
|
62
|
+
### Validate user intent before scaling
|
|
63
|
+
|
|
64
|
+
Generating pages for queries no one searches is the cleanest definition of index pollution. Before scaling, every template must answer:
|
|
65
|
+
|
|
66
|
+
1. **Does the templated query actually exist?** Pull search volume from any keyword tool (Ahrefs, SEMrush, Google Keyword Planner, GSC) on a sample of 20-50 rows. If the median row has 0 monthly searches, the template should not scale.
|
|
67
|
+
2. **What does the SERP look like for these queries?** Look at the existing top 10. If every result is a thin SEO-spam page, the SERP is winnable. If every result is a deep editorial article from a high-authority site, this template can't compete and shouldn't be built.
|
|
68
|
+
3. **What is the searcher's job-to-be-done on the page?** Write the job in one sentence. If you can't write it, the searcher doesn't have a job; the query is incidental and the page will not convert.
|
|
69
|
+
|
|
70
|
+
### The Zapier benchmark — what good looks like
|
|
71
|
+
|
|
72
|
+
Zapier's app-pair pages are the canonical reference: **63,000+ templated pages → 280,000+ monthly organic visits → material contribution to a $5B valuation**. The structural lessons:
|
|
73
|
+
|
|
74
|
+
- Every page has a unique data anchor (two real apps, real integration triggers, real action examples).
|
|
75
|
+
- One template, ruthlessly consistent across all pages.
|
|
76
|
+
- Intent is unambiguous — "connect [App A] and [App B]" — and the page delivers it in the first viewport.
|
|
77
|
+
- Internal links form a topical graph — every page links to other relevant app pairs, creating discovery paths for both users and crawlers.
|
|
78
|
+
- Pages with no genuine integration data are noindexed; only validated pairs are pushed to the index.
|
|
79
|
+
|
|
80
|
+
If your pSEO output cannot pass a Zapier-style audit on any random sampled row, the template isn't ready.
|
|
81
|
+
|
|
82
|
+
### Quality at scale — every page is a manual-review candidate
|
|
83
|
+
|
|
84
|
+
Quality and scale are not opposed; they are coupled. Every page in a pSEO project must pass a "would a human in this page's target audience be satisfied?" test. The fact that pages are templated does not exempt them from quality review — it just changes the unit of review from per-page to per-template-plus-sampled-rows.
|
|
85
|
+
|
|
86
|
+
Sample 1% of rows (minimum 20, maximum 200) and review them as a real reader would. If the sample shows thin or empty pages, fix the template or trim the data before pushing to scale. The verifier and any reviewer should be able to land on a random row and conclude that the page deserves to exist.
|
|
87
|
+
|
|
88
|
+
### No-code pSEO is a delivery mechanism, not a strategy
|
|
89
|
+
|
|
90
|
+
The "no-code pSEO" pipeline — spreadsheet/database + Airtable/Notion/Sheets + Webflow/Framer/Next.js + a CMS plugin or static-site generator — is a perfectly valid way to ship a programmatic site. It is not a strategy. The strategy is still data × template × intent. The no-code pipeline only matters once those three are locked. Reaching for tools before locking the triad is a tell that the project will fail.
|
|
91
|
+
|
|
92
|
+
### Index strategically — generate everything, index only what earns it
|
|
93
|
+
|
|
94
|
+
A pSEO project generates pages from data; it does not need to expose every generated page to search engines. Generate 10,000 rows; mark 8,000 as `noindex` because they lack a data anchor strong enough to satisfy intent; index the 2,000 that pass the per-page quality gate. As more data arrives (more reviews, more integration triggers, more entity coverage), additional pages graduate from `noindex` to indexable.
|
|
95
|
+
|
|
96
|
+
This is the single most important operational pattern in pSEO. Sites that index everything they generate get core-update flattened. Sites that gate indexing on data quality survive and compound.
|
|
97
|
+
|
|
98
|
+
### Cross-reference the operational layers
|
|
99
|
+
|
|
100
|
+
This playbook is the strategy. For execution mechanics, defer to:
|
|
101
|
+
|
|
102
|
+
- **`references/pseo-page-anatomy.md`** — universal pSEO page structure (breadcrumbs, TL;DR/answer block, FAQ schema, related-pages footer, llms.txt requirement, performance budgets). Every templated page must satisfy this anatomy.
|
|
103
|
+
- **`references/pseo-templates/blog-anatomy.md`** + **`blog-content-playbook.md`** — pSEO blog template.
|
|
104
|
+
- **`references/pseo-templates/use-case-anatomy.md`** + **`use-case-content-playbook.md`** — pSEO use-case template.
|
|
105
|
+
- **`references/pseo-templates/comparison-anatomy.md`** + **`comparison-content-playbook.md`** — pSEO head-to-head comparison template.
|
|
106
|
+
- **`references/pseo-templates/alternative-anatomy.md`** + **`alternative-content-playbook.md`** — pSEO alternatives-to template.
|
|
107
|
+
- **`playbooks/seo.md`** — measurement and strategy layer (3-Layer Presence/Readiness/Business Impact model).
|
|
108
|
+
- **`playbooks/aeo.md`** — passage-level citability for AI answer engines.
|
|
109
|
+
|
|
110
|
+
When this playbook and a reference disagree on a tactical detail, the reference wins on page mechanics; this playbook wins on the question of whether the project should exist at all and which rows are allowed to index.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Discipline Gates
|
|
115
|
+
|
|
116
|
+
### DISC-PSEO-01: Data × Template × Intent Triad — Tier 1
|
|
117
|
+
|
|
118
|
+
**Checks:** The pSEO project brief declares all three inputs explicitly — data source, template definition, and per-page user intent
|
|
119
|
+
**Against:** Project brief and a sampled row's rendered page
|
|
120
|
+
|
|
121
|
+
#### Evaluation Criteria
|
|
122
|
+
|
|
123
|
+
1. **All three inputs named**
|
|
124
|
+
- PASS: Brief explicitly names (a) the data source with row count and provenance, (b) the template with its required field map, and (c) the per-page user intent in one sentence
|
|
125
|
+
- WARN: Two of three named clearly; one is implicit or hand-waved
|
|
126
|
+
- FAIL: One or more of data, template, or intent is missing, vague, or "we'll figure it out as we go"
|
|
127
|
+
|
|
128
|
+
2. **Data source meets the defensibility floor**
|
|
129
|
+
- PASS: Data source is first-party, aggregated public + non-trivial cleaning, permissioned third-party, or AI-summarized with anchor data — and the brief states which
|
|
130
|
+
- WARN: Data source named but provenance unclear
|
|
131
|
+
- FAIL: Data is "AI-generated content for each row" with no underlying data anchor
|
|
132
|
+
|
|
133
|
+
### DISC-PSEO-02: Per-Page Unique Data Anchor — Tier 1
|
|
134
|
+
|
|
135
|
+
**Checks:** Every published page carries unique data that distinguishes it from every other page on the same template
|
|
136
|
+
**Against:** Sampled rows (minimum 20, drawn at random from the indexable set)
|
|
137
|
+
|
|
138
|
+
#### Evaluation Criteria
|
|
139
|
+
|
|
140
|
+
1. **Unique data per page**
|
|
141
|
+
- PASS: Every sampled page contains at least 3 distinct data fields populated from the row that are not present on any other indexable page on this template
|
|
142
|
+
- WARN: Most sampled pages unique but 1-2 pages share substantially identical data with another row
|
|
143
|
+
- FAIL: Sampled pages are template-only with no row-specific data, or rely entirely on AI-generated narrative with no anchored facts
|
|
144
|
+
|
|
145
|
+
2. **No empty placeholder fields**
|
|
146
|
+
- PASS: No sampled page has a visible field rendering as empty, "N/A", "TBD", "—", or a placeholder string
|
|
147
|
+
- WARN: 1-2 sampled pages have one minor field empty (e.g., optional metric) with the rest populated
|
|
148
|
+
- FAIL: Multiple sampled pages have primary content fields empty; template renders skeleton boxes
|
|
149
|
+
|
|
150
|
+
### DISC-PSEO-03: Intent Declared and Realized — Tier 1
|
|
151
|
+
|
|
152
|
+
**Checks:** Per-page user intent is declared in the brief and observably realized in the rendered page
|
|
153
|
+
**Against:** Project brief intent statement + sampled rendered pages
|
|
154
|
+
|
|
155
|
+
#### Evaluation Criteria
|
|
156
|
+
|
|
157
|
+
1. **Intent declared in brief**
|
|
158
|
+
- PASS: Brief states the per-page intent in one sentence as a job-to-be-done ("the searcher wants to X") and the template's primary H1 + TL;DR + above-fold CTA all answer that job
|
|
159
|
+
- WARN: Intent declared but only partially realized in the rendered page (e.g., H1 names the job but the page body answers a different one)
|
|
160
|
+
- FAIL: No intent declared, or the rendered page is structured around a different intent than the brief states
|
|
161
|
+
|
|
162
|
+
2. **Search-volume validation for sampled rows**
|
|
163
|
+
- PASS: At least 50% of sampled rows show non-zero monthly search volume for their target query (any reputable tool — Ahrefs, SEMrush, GKP, GSC for the few that already rank)
|
|
164
|
+
- WARN: 20-50% of sampled rows show non-zero search volume
|
|
165
|
+
- FAIL: Under 20% of sampled rows show any search demand — the template is generating queries no one types
|
|
166
|
+
|
|
167
|
+
### DISC-PSEO-04: Template Pre-Scale Test — Tier 1
|
|
168
|
+
|
|
169
|
+
**Checks:** The template was tested on a small set of pages and read by a human before being scaled
|
|
170
|
+
**Against:** Project history / commit log + a sampled review note
|
|
171
|
+
|
|
172
|
+
#### Evaluation Criteria
|
|
173
|
+
|
|
174
|
+
1. **Test set existed before scale**
|
|
175
|
+
- PASS: Project record shows the template was first published with 5-25 rows, reviewed end-to-end, iterated, and only then scaled to full row count
|
|
176
|
+
- WARN: Test set existed but no review iteration visible (template was scaled the same day it was created)
|
|
177
|
+
- FAIL: Template was scaled directly from 0 to the full row count with no intermediate test phase
|
|
178
|
+
|
|
179
|
+
### DISC-PSEO-05: Index Strategy & Quality Gate — Tier 1
|
|
180
|
+
|
|
181
|
+
**Checks:** Indexing is gated on per-page quality, not granted to every generated page by default
|
|
182
|
+
**Against:** Generated row count vs. indexable row count; robots/meta directives on sampled "thin" rows
|
|
183
|
+
|
|
184
|
+
#### Evaluation Criteria
|
|
185
|
+
|
|
186
|
+
1. **Generated vs. indexable separation**
|
|
187
|
+
- PASS: The project has more generated pages than indexable pages, with documented criteria for what graduates a page from `noindex` to indexable (e.g., "≥3 populated fields", "≥1 review", "≥non-zero search volume")
|
|
188
|
+
- WARN: All generated pages are indexed but the brief acknowledges the indexing strategy needs revisiting
|
|
189
|
+
- FAIL: Every generated page is indexed by default with no quality threshold; thin pages are visible in the sitemap
|
|
190
|
+
|
|
191
|
+
2. **Sampled thin pages carry `noindex`**
|
|
192
|
+
- PASS: Sampling pages that fail the per-page data threshold confirms they carry `noindex` or are excluded from the sitemap
|
|
193
|
+
- WARN: Some thin pages carry `noindex`, others slipped through
|
|
194
|
+
- FAIL: Thin pages are sitemapped and indexable
|
|
195
|
+
|
|
196
|
+
### DISC-PSEO-06: Internal Topical Graph — Tier 2
|
|
197
|
+
|
|
198
|
+
**Checks:** Templated pages link to other relevant templated pages, forming a discoverable topical graph rather than a flat list of orphans
|
|
199
|
+
**Against:** Sampled rendered pages + sitemap structure
|
|
200
|
+
|
|
201
|
+
#### Evaluation Criteria
|
|
202
|
+
|
|
203
|
+
1. **Related-page links on each page**
|
|
204
|
+
- PASS: Every sampled page renders at least 3 contextually relevant outbound internal links to other pages in the same template family or a related template (see `references/pseo-page-anatomy.md` — "Related pages" block)
|
|
205
|
+
- WARN: Related-page block exists but links are random or non-contextual
|
|
206
|
+
- FAIL: Pages are orphans — no outbound internal links to sibling templated pages
|
|
207
|
+
|
|
208
|
+
2. **Hub/index page exists for the template**
|
|
209
|
+
- PASS: A hub page indexes the template's rows (alphabetically, by category, or by data attribute) and is itself crawlable and internally linked from the site nav
|
|
210
|
+
- WARN: Hub exists but is buried — not linked from primary nav or footer
|
|
211
|
+
- FAIL: No hub page; rows are only discoverable via XML sitemap
|
|
212
|
+
|
|
213
|
+
### DISC-PSEO-07: Structured Data Per Template — Tier 2
|
|
214
|
+
|
|
215
|
+
**Checks:** Each template ships with the schema markup type appropriate to its content shape, with all required fields populated from row data
|
|
216
|
+
**Against:** Sampled pages' JSON-LD blocks (see `references/pseo-page-anatomy.md`)
|
|
217
|
+
|
|
218
|
+
#### Evaluation Criteria
|
|
219
|
+
|
|
220
|
+
1. **Schema type matches template shape**
|
|
221
|
+
- PASS: Schema type is appropriate (Article + FAQPage for `pseo-blog`; Article + FAQPage + SoftwareApplication or Product for `pseo-use-case`; Article + FAQPage + appropriate comparison schema for `pseo-comparison`/`pseo-alternative`); BreadcrumbList is on every page
|
|
222
|
+
- WARN: Schema type correct but one or two required properties not populated from row data
|
|
223
|
+
- FAIL: Schema missing, wrong type for the template, or boilerplate (same author, date, publisher on every page when row-specific fields exist)
|
|
224
|
+
|
|
225
|
+
2. **Row-specific schema fields**
|
|
226
|
+
- PASS: At least 3 schema fields per page are populated from the row (e.g., `name`, `applicationCategory`, `aggregateRating`, `offers.price` for software-app templates)
|
|
227
|
+
- WARN: Schema present but most fields are template-static, not row-specific
|
|
228
|
+
- FAIL: Schema fields are identical across sampled pages
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Base Gate Overrides
|
|
233
|
+
|
|
234
|
+
| Base Gate ID | Default Tier | Override Tier | Reason |
|
|
235
|
+
|-------------|-------------|---------------|--------|
|
|
236
|
+
| GATE-10 | Tier 2 (advisory) | Tier 1 (blocking) | Format correctness — schema, headings, canonicals, sitemap inclusion — is the mechanism by which a templated page is crawled, indexed, and rendered in the SERP. A pSEO site cannot tolerate template-level format defects because every defect multiplies by the row count. |
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Format Rules
|
|
241
|
+
|
|
242
|
+
- **Minimum unique content per page:** At least 3 distinct row-derived data fields visible above the fold; at least 150 words of row-anchored body content (not template boilerplate). Pages below this threshold must be `noindex` until they reach it.
|
|
243
|
+
- **One template per asset type:** A single canonical template per `asset_type` (one for `pseo-blog`, one for `pseo-use-case`, etc.). Variants are template branches, not separate templates, and require a documented reason in the brief.
|
|
244
|
+
- **Template field manifest:** Every template declares the list of fields it reads from the data source. Every field is either marked `required` (page is `noindex` if empty) or `optional` (page renders without the field; no placeholder text).
|
|
245
|
+
- **Required schema per template family:** `BreadcrumbList` on every page + `Article` minimum, with `FAQPage` whenever the page renders an FAQ block. Use-case and comparison templates additionally require `SoftwareApplication` or `Product` schema with row-specific properties. Schema fields must be populated from row data, not hard-coded defaults.
|
|
246
|
+
- **URL structure:** Predictable, hyphen-separated, derived from row data (e.g., `/integrations/{app-a}-{app-b}/`, `/alternatives/{tool-slug}/`). No query strings on indexable pages.
|
|
247
|
+
- **Canonical:** Self-referencing on every indexable templated page. Pairwise comparison pages (`A vs B` and `B vs A`) must canonicalize to one direction, not both.
|
|
248
|
+
- **Sitemap inclusion:** Only indexable pages appear in the XML sitemap. Generated-but-`noindex` rows are excluded.
|
|
249
|
+
- **Internal linking:** Every templated page renders at minimum 3 contextual links to sibling pages in the same template family, plus 1 link to the template's hub page. See "Related pages" block in `references/pseo-page-anatomy.md`.
|
|
250
|
+
- **llms.txt:** Site root must list all indexable pSEO routes by template family with one-line descriptions (per `references/pseo-page-anatomy.md`).
|
|
251
|
+
- **Performance per template family:** LCP < 2.5s, CLS < 0.1, INP < 200ms across the template family at p75 (per CrUX). A failing template family blocks scale.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Examples
|
|
256
|
+
|
|
257
|
+
### Good — Use-case template with anchor data + intent
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
Data source: 1,200 real customer use-case write-ups exported from our
|
|
261
|
+
product analytics, each with: industry, team size, problem solved,
|
|
262
|
+
workflow before, workflow after, hours saved, named tool replaced.
|
|
263
|
+
Template (one): pseo-use-case template, fields = [industry, team_size,
|
|
264
|
+
problem, before_workflow, after_workflow, hours_saved, tool_replaced,
|
|
265
|
+
customer_quote, customer_logo].
|
|
266
|
+
Per-page intent: "I am [industry] at [team_size] and I want to know if
|
|
267
|
+
[our_product] solves [problem]." One sentence, in the brief.
|
|
268
|
+
|
|
269
|
+
Pre-scale test: published 12 rows, read all 12 as a buyer in each industry,
|
|
270
|
+
fixed the template's "after workflow" rendering twice before scaling.
|
|
271
|
+
Scaled to 1,200; of those, 240 carry `noindex` because the `customer_quote`
|
|
272
|
+
field is empty and we don't ship pages without real customer language.
|
|
273
|
+
Index: 960 indexable pages, all in the sitemap, all in /llms.txt.
|
|
274
|
+
Internal links: each page links to 3 same-industry sibling pages + the
|
|
275
|
+
/use-cases/ hub page. Hub is in the primary nav.
|
|
276
|
+
Schema: Article + FAQPage + SoftwareApplication, with row-specific
|
|
277
|
+
`applicationCategory`, `aggregateRating` from customer data, and
|
|
278
|
+
`offers.price` from the pricing column.
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Good — Alternatives template with strategic index gating
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
Data source: our team manually wrote 60 alternative-tool comparisons over
|
|
285
|
+
6 months, each with: competitor name, our positioning differentiator,
|
|
286
|
+
three named feature gaps, pricing comparison, when-to-pick-each guidance.
|
|
287
|
+
Template: pseo-alternative template.
|
|
288
|
+
Per-page intent: "I am evaluating [competitor] and want to know if
|
|
289
|
+
[our_product] is a fit — what's different, and when does each win?"
|
|
290
|
+
|
|
291
|
+
The team also AI-generated 400 additional rows for long-tail competitors
|
|
292
|
+
with thinner data. Decision: only the 60 hand-written rows are indexed;
|
|
293
|
+
the 400 generated rows render with `noindex` until a human writes at
|
|
294
|
+
least three concrete differentiators per row.
|
|
295
|
+
Result expectation: 60 high-quality indexed pages compounding over time;
|
|
296
|
+
no thin-content liability dragging the domain down.
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Bad — Template without a data anchor
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
Brief: "Generate 5,000 'Best [Tool] for [Use Case]' pages by combining
|
|
303
|
+
our 100 tools with our 50 use cases. AI writes the body of each page."
|
|
304
|
+
Problems:
|
|
305
|
+
- No data source. AI-generated narrative is not a data anchor.
|
|
306
|
+
- No intent validation. Most of the 5,000 query combinations have zero
|
|
307
|
+
search volume.
|
|
308
|
+
- No pre-scale test. Scaling 100 × 50 = 5,000 in one batch with no
|
|
309
|
+
template iteration.
|
|
310
|
+
- Every page is indexed by default — no quality gate, no `noindex` on
|
|
311
|
+
the 4,000 rows with no real differentiator.
|
|
312
|
+
Verdict: this is not pSEO. This is template-shaped spam. The first
|
|
313
|
+
core update will flatten it.
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Bad — Thin-content empty-field pages
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
Generated 8,000 city-by-service pages. Sampled 20 at random and found:
|
|
320
|
+
- 14 pages render "Service: TBD" in the H2 because the city has no
|
|
321
|
+
data in our database.
|
|
322
|
+
- 11 pages have a TL;DR that reads "[Service] in [City] is available
|
|
323
|
+
through [Provider]." — pure template, no row content.
|
|
324
|
+
- 6 pages have an FAQ block with 4 identical questions across all
|
|
325
|
+
sampled rows.
|
|
326
|
+
- 0 pages link to other city pages — the related-pages block renders
|
|
327
|
+
empty.
|
|
328
|
+
Verdict: template is structurally fine; data is too thin to populate
|
|
329
|
+
it. Either (a) enrich the data before scaling, or (b) `noindex`
|
|
330
|
+
everything except the 800 rows with full data and ship those.
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Bad — Two-axis explosion with no intent gating
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
Brief: "Generate pages for every combination of [200 cities] × [40
|
|
337
|
+
services] × [12 months] = 96,000 pages."
|
|
338
|
+
Problems:
|
|
339
|
+
- Three-axis explosion produces a long tail where 90%+ of rows have
|
|
340
|
+
zero search demand.
|
|
341
|
+
- Intent dilutes per page — the searcher's job is unclear ("is this a
|
|
342
|
+
monthly availability check? a service finder? a city guide?").
|
|
343
|
+
- Internal-linking graph becomes unmanageable; pages become orphans
|
|
344
|
+
in a sea of templated noise.
|
|
345
|
+
Fix: collapse to one axis ([city × service] = 8,000), gate indexing
|
|
346
|
+
on real search volume per row, drop the time dimension into the
|
|
347
|
+
body content (not the URL).
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Anti-Patterns
|
|
353
|
+
|
|
354
|
+
1. **Pure template with no per-page data** — Generating thousands of pages where the only difference between rows is a swapped name. AI-paraphrased boilerplate is not data. Without a row-specific anchor, every page is a near-duplicate and the engine will collapse them.
|
|
355
|
+
|
|
356
|
+
2. **Scaling before validating the template** — Going from 0 to 10,000 pages on the day the template is built. Without a test phase of 5-25 pages reviewed end-to-end by a human, structural defects multiply by the row count and become unfixable at scale.
|
|
357
|
+
|
|
358
|
+
3. **No intent variation across templates** — Treating every templated page as if it serves the same intent. A `pseo-comparison` page ("A vs B") has different searcher intent from a `pseo-alternative` page ("alternatives to X") even when the underlying entities overlap. Templates must be intent-distinguished.
|
|
359
|
+
|
|
360
|
+
4. **Index-stuffing — every generated page indexed by default** — Pushing the entire row count into the sitemap regardless of per-page quality. The correct default is `noindex` for any row missing required fields; pages graduate to indexable only when they meet the quality threshold.
|
|
361
|
+
|
|
362
|
+
5. **AI-generated content with no anchor data** — Using an LLM to write the body of templated pages without a structured data source under it. Without anchor data, the output is plausible-looking text with no factual content per page — the worst kind of pSEO because it looks reviewable but isn't.
|
|
363
|
+
|
|
364
|
+
6. **No internal linking — orphan templated pages** — Generating pages reachable only via the XML sitemap. Without a topical graph linking related pages and a hub page indexing the family, the templated pages cannot accumulate internal equity and cannot be navigated by a real user.
|
|
365
|
+
|
|
366
|
+
7. **No-code tooling before strategy is locked** — Reaching for Airtable, Webflow, or a CMS plugin before the data × template × intent triad is settled. The pipeline is a delivery mechanism; the triad is the strategy. Tooling-first projects mistake motion for progress.
|
|
367
|
+
|
|
368
|
+
8. **Mixed axes ([thing] × [location] × [time] × [category])** — Multi-axis templates explode the row count into queries no one searches and dilute per-page intent. Successful pSEO sites pick one axis and commit; multi-axis is the signature of a project that hasn't decided what it is.
|
|
369
|
+
|
|
370
|
+
9. **Schema markup that's identical across every row** — Ships the same `author`, `datePublished`, `aggregateRating`, and `name` field on every templated page. Schema must be populated from row data, not template defaults, or it provides no incremental signal.
|
|
371
|
+
|
|
372
|
+
10. **Treating a pSEO project as a one-shot launch** — Scaling 10,000 pages, declaring victory, and walking away. pSEO compounds only when the data refreshes, the template iterates, and the index set grows as new rows earn quality. A frozen pSEO site decays.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Metrics
|
|
377
|
+
|
|
378
|
+
Every metric carries a source and is reported per template family, not aggregated across the site. Aggregated pSEO metrics hide which template is winning and which is bleeding.
|
|
379
|
+
|
|
380
|
+
### Indexation health
|
|
381
|
+
|
|
382
|
+
- **Generated rows vs. indexable rows vs. indexed rows** — Source: row database + sitemap + GSC Coverage report. Confidence: high. The three numbers should converge over time but never be identical at launch. Track per template family.
|
|
383
|
+
- **`noindex` ratio per template** — Source: site audit + GSC. Confidence: high. A healthy pSEO project has a non-zero `noindex` rate per template — that proves the quality gate is functioning.
|
|
384
|
+
- **Sitemap inclusion accuracy** — Source: XML sitemap audit vs. row database. Confidence: high. Indexable rows present in sitemap; `noindex` rows absent. Per template, per release.
|
|
385
|
+
|
|
386
|
+
### Organic performance per template
|
|
387
|
+
|
|
388
|
+
- **Organic clicks per template family** — Source: GSC, grouped by URL prefix. Confidence: high. Reported per template, never aggregated to a single "pSEO total" — a winning template hides a losing one.
|
|
389
|
+
- **Organic impressions per template** — Source: GSC. Confidence: high. Per template, weekly.
|
|
390
|
+
- **Average position for the template's target query pattern** — Source: GSC URL pattern filter. Confidence: medium (averaged). 30/60/90 day windows.
|
|
391
|
+
- **Clicks per indexed page (yield)** — Source: GSC clicks ÷ indexed page count for the template. Confidence: high. This is the single most diagnostic pSEO metric — yield trending down means the index is bloated with thin pages and the quality gate needs to tighten.
|
|
392
|
+
|
|
393
|
+
### Conversion per intent
|
|
394
|
+
|
|
395
|
+
- **Conversion rate per template family** — Source: GA4 or product analytics with UTM-tagged pSEO CTAs. Confidence: medium. Track signups/trials/leads from each template family separately. A `pseo-comparison` template should out-convert a `pseo-blog` template; if it doesn't, the comparison intent isn't being served.
|
|
396
|
+
- **Time-to-conversion from pSEO landing** — Source: product analytics with session attribution. Confidence: medium. pSEO-acquired users should convert in a measurable window; if they bounce, the intent declared in the brief isn't matching the page.
|
|
397
|
+
- **Activation rate from pSEO-acquired users** — Source: product analytics. Confidence: high (deterministic event). Compared against other acquisition cohorts to confirm pSEO traffic isn't drive-by.
|
|
398
|
+
|
|
399
|
+
### Quality and freshness
|
|
400
|
+
|
|
401
|
+
- **Per-template Core Web Vitals pass rate** — Source: CrUX. Confidence: high. A failing template family blocks further scaling. Per template.
|
|
402
|
+
- **AI Overview / answer engine citation rate** — Source: AI citation tracker (Profound, Otterly, manual sampling). Confidence: low-medium. Per template; pSEO pages should be citation-ready (see `playbooks/aeo.md`).
|
|
403
|
+
- **Data freshness per row** — Source: row database `updated_at`. Confidence: high. Rows older than the template's freshness threshold flag for refresh; stale rows lose ranking and citation eligibility.
|
|
404
|
+
|
|
405
|
+
### Reporting discipline
|
|
406
|
+
|
|
407
|
+
- Never report pSEO health as a single number. Report per template family.
|
|
408
|
+
- Always pair an indexation number with a yield number — 10,000 indexed pages at 0.1 clicks each is a worse outcome than 1,000 indexed pages at 5 clicks each.
|
|
409
|
+
- When a template's yield is trending down, the response is to tighten the quality gate (more `noindex`), not to generate more rows.
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## Sources
|
|
414
|
+
|
|
415
|
+
1. **Ian Nuttall — Practical Programmatic SEO (home)** — https://practicalprogrammatic.com/
|
|
416
|
+
2. **Ian Nuttall — No-Code Programmatic SEO course** — https://iannuttall.gumroad.com/l/no-code-programmatic-seo
|
|
417
|
+
3. **Practical Programmatic — Zapier case study** — https://practicalprogrammatic.com/examples/zapier
|
|
418
|
+
4. **Backlinko — Programmatic SEO overview (corroborating two-axis patterns)** — https://backlinko.com/programmatic-seo
|
|
419
|
+
5. **Single Grain — Programmatic SEO playbook (agency-level execution reference)** — https://www.singlegrain.com/blog/pseo-playbook/
|
|
420
|
+
|
|
421
|
+
Cross-link references inside this repository:
|
|
422
|
+
|
|
423
|
+
- **`references/pseo-page-anatomy.md`** — universal pSEO page structure shared across all four template types.
|
|
424
|
+
- **`references/pseo-templates/`** — per-template anatomy and content playbooks (`blog-`, `use-case-`, `comparison-`, `alternative-`).
|
|
425
|
+
- **`playbooks/seo.md`** — Aleyda Solis's 3-Layer measurement model that pSEO metrics plug into.
|
|
426
|
+
- **`playbooks/aeo.md`** — Mike King's Relevance Engineering for passage-level citability of templated pages.
|