aeorank 2.0.0 → 2.1.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/README.md CHANGED
@@ -41,38 +41,90 @@ console.log(result.opportunities); // Prioritized improvements
41
41
 
42
42
  ## What It Checks
43
43
 
44
- AEORank evaluates 28 criteria across 4 categories that determine how AI engines (ChatGPT, Claude, Perplexity, Google AI Overviews) discover, parse, and cite your content:
45
-
46
- | # | Criterion | Weight | Category |
47
- |---|-----------|--------|----------|
48
- | 1 | llms.txt File | 8% | Discovery |
49
- | 2 | Schema.org Structured Data | 8% | Structure |
50
- | 3 | Q&A Content Format | 12% | Content |
51
- | 4 | Clean, Crawlable HTML | 8% | Structure |
52
- | 5 | Entity Authority & NAP Consistency | 8% | Authority |
53
- | 6 | robots.txt for AI Crawlers | 3% | Discovery |
54
- | 7 | Comprehensive FAQ Section | 8% | Content |
55
- | 8 | Original Data & Expert Analysis | 12% | Content |
56
- | 9 | Internal Linking Structure | 8% | Structure |
57
- | 10 | Semantic HTML5 & Accessibility | 4% | Structure |
58
- | 11 | Content Freshness Signals | 6% | Content |
59
- | 12 | Sitemap Completeness | 3% | Discovery |
60
- | 13 | RSS/Atom Feed | 2% | Discovery |
61
- | 14 | Table & List Extractability | 5% | Structure |
62
- | 15 | Definition Patterns | 4% | Content |
63
- | 16 | Direct Answer Paragraphs | 7% | Content |
64
- | 17 | Content Licensing & AI Permissions | 3% | Discovery |
65
- | 18 | Author & Expert Schema | 4% | Authority |
66
- | 19 | Fact & Data Density | 8% | Content |
67
- | 20 | Canonical URL Strategy | 2% | Structure |
68
- | 21 | Content Publishing Velocity | 3% | Content |
69
- | 22 | Schema Coverage & Depth | 2% | Structure |
70
- | 23 | Speakable Schema | 2% | Structure |
71
- | 24 | Query-Answer Alignment | 6% | Content |
72
- | 25 | Content Cannibalization | 5% | Content |
73
- | 26 | Visible Date Signal | 4% | Content |
74
- | 27 | **Topic Coherence** | **14%** | **Content** |
75
- | 28 | **Content Depth** | **6%** | **Content** |
44
+ AEORank evaluates 28 criteria that determine how AI engines (ChatGPT, Claude, Perplexity, Google AI Overviews) discover, parse, and cite your content. Criteria are organized into three tiers by impact on real-world AI citations:
45
+
46
+ ### Scoring Tiers (by importance)
47
+
48
+ **Content Substance (~55%)** - *Why* an AI engine would cite you:
49
+
50
+ | Criterion | Weight | What it measures |
51
+ |-----------|--------|------------------|
52
+ | Topic Coherence | 14% | Blog content focus on core expertise vs scattered topics |
53
+ | Original Data & Expert Analysis | 10% | Proprietary research, case studies, unique data points |
54
+ | Content Depth | 7% | Article length, heading structure, deep vs thin pages |
55
+ | Fact & Data Density | 6% | Specific numbers, statistics, data points per page |
56
+ | Direct Answer Paragraphs | 5% | Concise answer paragraphs after question headings |
57
+ | Q&A Content Format | 5% | Question-format headings (What, How, Why) with answers |
58
+ | Query-Answer Alignment | 5% | Every question heading followed by a direct answer |
59
+ | Comprehensive FAQ Section | 4% | Dedicated FAQ with FAQPage schema markup |
60
+
61
+ **Content Organization (~30%)** - *How* easily AI can extract and trust your content:
62
+
63
+ | Criterion | Weight | What it measures |
64
+ |-----------|--------|------------------|
65
+ | Entity Authority & NAP Consistency | 5% | Organization schema, consistent name/address/phone |
66
+ | Internal Linking Structure | 4% | Topic clusters, breadcrumbs, reachability from homepage |
67
+ | Content Freshness Signals | 4% | dateModified schema, visible dates, recent content |
68
+ | Schema.org Structured Data | 3% | JSON-LD blocks (Organization, Article, FAQPage, etc.) |
69
+ | Author & Expert Schema | 3% | Person schema with credentials and expertise |
70
+ | Table & List Extractability | 3% | HTML tables with headers, ordered/unordered lists |
71
+ | Definition Patterns | 2% | Clear "X is defined as..." patterns for key terms |
72
+ | Visible Date Signal | 2% | Visible publication dates with `<time>` elements |
73
+ | Semantic HTML5 & Accessibility | 2% | Semantic elements (main, article, nav), ARIA, lang |
74
+ | Clean, Crawlable HTML | 2% | HTTPS, meta tags, proper heading hierarchy |
75
+
76
+ **Technical Plumbing (~15%)** - *Whether* AI crawlers can find you (table stakes):
77
+
78
+ | Criterion | Weight | What it measures |
79
+ |-----------|--------|------------------|
80
+ | Content Cannibalization | 2% | Overlapping pages competing for the same topic |
81
+ | llms.txt File | 2% | /llms.txt with site description and key page URLs |
82
+ | robots.txt for AI Crawlers | 2% | GPTBot, ClaudeBot, PerplexityBot access |
83
+ | Content Publishing Velocity | 2% | Regular publishing cadence in sitemap |
84
+ | Content Licensing & AI Permissions | 2% | /ai.txt file, license schema for AI usage |
85
+ | Sitemap Completeness | 1% | sitemap.xml with lastmod dates |
86
+ | Canonical URL Strategy | 1% | Self-referencing canonical tags |
87
+ | RSS/Atom Feed | 1% | RSS feed linked from homepage |
88
+ | Schema Coverage & Depth | 1% | Schema markup on inner pages, not just homepage |
89
+ | Speakable Schema | 1% | SpeakableSpecification for voice assistants |
90
+
91
+ > **Coherence Gate:** Sites with topic coherence below 6/10 are score-capped regardless of technical perfection. A scattered site with perfect robots.txt, llms.txt, and schema will score lower than a focused site with mediocre technical implementation.
92
+
93
+ <details>
94
+ <summary>All 28 criteria (numbered list)</summary>
95
+
96
+ | # | Criterion | Weight | Tier |
97
+ |---|-----------|--------|------|
98
+ | 1 | llms.txt File | 2% | Plumbing |
99
+ | 2 | Schema.org Structured Data | 3% | Organization |
100
+ | 3 | Q&A Content Format | 5% | Substance |
101
+ | 4 | Clean, Crawlable HTML | 2% | Organization |
102
+ | 5 | Entity Authority & NAP Consistency | 5% | Organization |
103
+ | 6 | robots.txt for AI Crawlers | 2% | Plumbing |
104
+ | 7 | Comprehensive FAQ Section | 4% | Substance |
105
+ | 8 | Original Data & Expert Analysis | 10% | Substance |
106
+ | 9 | Internal Linking Structure | 4% | Organization |
107
+ | 10 | Semantic HTML5 & Accessibility | 2% | Organization |
108
+ | 11 | Content Freshness Signals | 4% | Organization |
109
+ | 12 | Sitemap Completeness | 1% | Plumbing |
110
+ | 13 | RSS/Atom Feed | 1% | Plumbing |
111
+ | 14 | Table & List Extractability | 3% | Organization |
112
+ | 15 | Definition Patterns | 2% | Organization |
113
+ | 16 | Direct Answer Paragraphs | 5% | Substance |
114
+ | 17 | Content Licensing & AI Permissions | 2% | Plumbing |
115
+ | 18 | Author & Expert Schema | 3% | Organization |
116
+ | 19 | Fact & Data Density | 6% | Substance |
117
+ | 20 | Canonical URL Strategy | 1% | Plumbing |
118
+ | 21 | Content Publishing Velocity | 2% | Plumbing |
119
+ | 22 | Schema Coverage & Depth | 1% | Plumbing |
120
+ | 23 | Speakable Schema | 1% | Plumbing |
121
+ | 24 | Query-Answer Alignment | 5% | Substance |
122
+ | 25 | Content Cannibalization | 2% | Plumbing |
123
+ | 26 | Visible Date Signal | 2% | Organization |
124
+ | 27 | Topic Coherence | 14% | Substance |
125
+ | 28 | Content Depth | 7% | Substance |
126
+
127
+ </details>
76
128
 
77
129
  ## CLI Options
78
130
 
@@ -296,9 +348,26 @@ console.log(crawlResult.discoveredUrls.length); // Total URLs found
296
348
 
297
349
  AEORank scores each individual page (0-100) against the 14 criteria that apply at page level. Instead of only seeing "your site scores 62," you get "your /about page scores 45, your /blog/guide scores 78."
298
350
 
299
- The 14 per-page criteria: Schema.org Structured Data, Q&A Content Format, Clean Crawlable HTML, FAQ Section Content, Original Data & Expert Content, Query-Answer Alignment, Content Freshness Signals, Table & List Extractability, Direct Answer Paragraphs, Semantic HTML5 & Accessibility, Fact & Data Density, Definition Patterns, Canonical URL Strategy, Visible Date Signal.
300
-
301
- The remaining 14 criteria (llms.txt, robots.txt, sitemap, RSS, entity consistency, internal linking, content licensing, author schema, content velocity, schema coverage, speakable schema, content cannibalization, topic coherence, content depth) are site-level only.
351
+ The 14 per-page criteria follow the same substance-first weighting as the site-level score:
352
+
353
+ | Tier | Per-Page Criteria | Weight |
354
+ |------|-------------------|--------|
355
+ | **Substance** | Original Data & Expert Content | 10% |
356
+ | | Fact & Data Density | 6% |
357
+ | | Direct Answer Paragraphs | 5% |
358
+ | | Q&A Content Format | 5% |
359
+ | | Query-Answer Alignment | 5% |
360
+ | | FAQ Section Content | 4% |
361
+ | **Organization** | Content Freshness Signals | 4% |
362
+ | | Schema.org Structured Data | 3% |
363
+ | | Table & List Extractability | 3% |
364
+ | | Definition Patterns | 2% |
365
+ | | Visible Date Signal | 2% |
366
+ | | Semantic HTML5 & Accessibility | 2% |
367
+ | | Clean, Crawlable HTML | 2% |
368
+ | **Plumbing** | Canonical URL Strategy | 1% |
369
+
370
+ The remaining 14 criteria are site-level only: llms.txt, robots.txt, sitemap, RSS, entity consistency, internal linking, content licensing, author schema, content velocity, schema coverage, speakable schema, content cannibalization, topic coherence, and content depth.
302
371
 
303
372
  ### CLI Output
304
373
 
package/dist/browser.d.ts CHANGED
@@ -376,7 +376,7 @@ declare function analyzeAllPages(siteData: SiteData): PageReview[];
376
376
 
377
377
  /**
378
378
  * Per-page AEO scoring.
379
- * Evaluates 14 of 26 criteria that apply at individual page level.
379
+ * Evaluates 14 of 28 criteria that apply at individual page level.
380
380
  * Produces a 0-100 AEO score per page.
381
381
  */
382
382
 
package/dist/browser.js CHANGED
@@ -2069,40 +2069,58 @@ function auditSiteFromData(data) {
2069
2069
 
2070
2070
  // src/scoring.ts
2071
2071
  var WEIGHTS = {
2072
- // ─── Core Content (high weight - these determine real AI citation quality) ──
2073
- qa_content_format: 0.12,
2074
- original_data: 0.12,
2072
+ // ─── Content Substance (~55%) ─────────────────────────────────────────────
2073
+ // WHY an AI engine would cite you. These drive citation quality directly.
2075
2074
  topic_coherence: 0.14,
2076
- // NEW v2.0: biggest predictor of AI citation quality
2077
- fact_density: 0.08,
2078
- direct_answer_density: 0.07,
2079
- content_depth: 0.06,
2080
- // NEW v2.0: substantive content vs thin pages
2081
- // ─── Structure & Discovery (medium weight - technical readiness) ────────────
2082
- schema_markup: 0.08,
2083
- llms_txt: 0.08,
2084
- clean_html: 0.08,
2085
- entity_consistency: 0.08,
2086
- faq_section: 0.08,
2087
- internal_linking: 0.08,
2088
- // ─── Content Signals (moderate weight) ──────────────────────────────────────
2089
- content_freshness: 0.06,
2090
- table_list_extractability: 0.05,
2091
- query_answer_alignment: 0.06,
2092
- definition_patterns: 0.04,
2093
- author_schema_depth: 0.04,
2094
- content_cannibalization: 0.05,
2095
- visible_date_signal: 0.04,
2096
- semantic_html: 0.04,
2097
- // ─── Plumbing (low weight - nice to have but not what drives citations) ─────
2098
- robots_txt: 0.03,
2099
- sitemap_completeness: 0.03,
2100
- content_velocity: 0.03,
2101
- rss_feed: 0.02,
2102
- content_licensing: 0.03,
2103
- canonical_url: 0.02,
2104
- schema_coverage: 0.02,
2105
- speakable_schema: 0.02
2075
+ // Topical authority - THE gating signal
2076
+ original_data: 0.1,
2077
+ // Unique value AI can't find elsewhere
2078
+ content_depth: 0.07,
2079
+ // Comprehensive vs thin coverage
2080
+ fact_density: 0.06,
2081
+ // Information density per page
2082
+ direct_answer_density: 0.05,
2083
+ // Direct answers to queries
2084
+ qa_content_format: 0.05,
2085
+ // Answer-shaped content structure
2086
+ query_answer_alignment: 0.05,
2087
+ // Relevance to actual AI queries
2088
+ faq_section: 0.04,
2089
+ // Structured Q&A pairs
2090
+ // ─── Content Organization (~30%) ──────────────────────────────────────────
2091
+ // HOW easily AI engines can extract and trust your content.
2092
+ entity_consistency: 0.05,
2093
+ // Brand authority and E-E-A-T
2094
+ internal_linking: 0.04,
2095
+ // Site structure and topic clusters
2096
+ content_freshness: 0.04,
2097
+ // Recency signals
2098
+ schema_markup: 0.03,
2099
+ // Structured data for discovery
2100
+ author_schema_depth: 0.03,
2101
+ // Expert attribution
2102
+ table_list_extractability: 0.03,
2103
+ // Extractable structured data
2104
+ definition_patterns: 0.02,
2105
+ // Clear definitions
2106
+ visible_date_signal: 0.02,
2107
+ // Publication date trust
2108
+ semantic_html: 0.02,
2109
+ // Clean semantic structure
2110
+ clean_html: 0.02,
2111
+ // Parseable markup
2112
+ // ─── Technical Plumbing (~15%) ────────────────────────────────────────────
2113
+ // WHETHER AI crawlers can find you. Table stakes with diminishing returns.
2114
+ content_cannibalization: 0.02,
2115
+ llms_txt: 0.02,
2116
+ robots_txt: 0.02,
2117
+ content_velocity: 0.02,
2118
+ content_licensing: 0.02,
2119
+ sitemap_completeness: 0.01,
2120
+ canonical_url: 0.01,
2121
+ rss_feed: 0.01,
2122
+ schema_coverage: 0.01,
2123
+ speakable_schema: 0.01
2106
2124
  };
2107
2125
  function calculateOverallScore(criteria) {
2108
2126
  let totalWeight = 0;
@@ -2113,7 +2131,13 @@ function calculateOverallScore(criteria) {
2113
2131
  totalWeight += weight;
2114
2132
  }
2115
2133
  if (totalWeight === 0) return 0;
2116
- return Math.round(weightedSum / totalWeight);
2134
+ let score = Math.round(weightedSum / totalWeight);
2135
+ const coherence = criteria.find((c) => c.criterion === "topic_coherence");
2136
+ if (coherence && coherence.score < 6) {
2137
+ const cap2 = 35 + coherence.score * 5;
2138
+ score = Math.min(score, cap2);
2139
+ }
2140
+ return score;
2117
2141
  }
2118
2142
 
2119
2143
  // src/scorecard-builder.ts
@@ -2231,32 +2255,37 @@ function buildDetailedFindings(results) {
2231
2255
 
2232
2256
  // src/narrative-generator.ts
2233
2257
  var CRITERION_WEIGHTS = {
2234
- llms_txt: 0.1,
2235
- schema_markup: 0.15,
2236
- qa_content_format: 0.15,
2237
- clean_html: 0.1,
2238
- entity_consistency: 0.1,
2239
- robots_txt: 0.05,
2240
- faq_section: 0.1,
2258
+ // Content Substance (~55%)
2259
+ topic_coherence: 0.14,
2241
2260
  original_data: 0.1,
2242
- internal_linking: 0.1,
2243
- semantic_html: 0.05,
2244
- content_freshness: 0.07,
2245
- sitemap_completeness: 0.05,
2246
- rss_feed: 0.03,
2247
- table_list_extractability: 0.07,
2248
- definition_patterns: 0.04,
2249
- direct_answer_density: 0.07,
2250
- content_licensing: 0.04,
2251
- author_schema_depth: 0.04,
2252
- fact_density: 0.05,
2253
- canonical_url: 0.04,
2254
- content_velocity: 0.03,
2255
- schema_coverage: 0.03,
2256
- speakable_schema: 0.03,
2257
- query_answer_alignment: 0.08,
2258
- content_cannibalization: 0.05,
2259
- visible_date_signal: 0.04
2261
+ content_depth: 0.07,
2262
+ fact_density: 0.06,
2263
+ direct_answer_density: 0.05,
2264
+ qa_content_format: 0.05,
2265
+ query_answer_alignment: 0.05,
2266
+ faq_section: 0.04,
2267
+ // Content Organization (~30%)
2268
+ entity_consistency: 0.05,
2269
+ internal_linking: 0.04,
2270
+ content_freshness: 0.04,
2271
+ schema_markup: 0.03,
2272
+ author_schema_depth: 0.03,
2273
+ table_list_extractability: 0.03,
2274
+ definition_patterns: 0.02,
2275
+ visible_date_signal: 0.02,
2276
+ semantic_html: 0.02,
2277
+ clean_html: 0.02,
2278
+ // Technical Plumbing (~15%)
2279
+ content_cannibalization: 0.02,
2280
+ llms_txt: 0.02,
2281
+ robots_txt: 0.02,
2282
+ content_velocity: 0.02,
2283
+ content_licensing: 0.02,
2284
+ sitemap_completeness: 0.01,
2285
+ canonical_url: 0.01,
2286
+ rss_feed: 0.01,
2287
+ schema_coverage: 0.01,
2288
+ speakable_schema: 0.01
2260
2289
  };
2261
2290
  var OPPORTUNITY_TEMPLATES = {
2262
2291
  llms_txt: {
@@ -2388,6 +2417,16 @@ var OPPORTUNITY_TEMPLATES = {
2388
2417
  name: "Add Visible Date Signals",
2389
2418
  effort: "Low",
2390
2419
  description: "Display publication/modification dates visibly using <time> elements and add datePublished/dateModified to JSON-LD schema."
2420
+ },
2421
+ topic_coherence: {
2422
+ name: "Focus Content on Core Topics",
2423
+ effort: "High",
2424
+ description: 'Ensure blog content consistently covers your core expertise areas rather than scattering across unrelated topics. AI engines build authority models - a site about "Medicare coverage" that also publishes about humidifiers and groceries dilutes its topical authority.'
2425
+ },
2426
+ content_depth: {
2427
+ name: "Increase Content Depth",
2428
+ effort: "Medium",
2429
+ description: "Expand articles to 1000+ words with structured H2/H3 sections, comparison tables, and expert analysis. Thin content (under 300 words) is rarely cited by AI engines. Deep, well-structured articles demonstrate expertise."
2391
2430
  }
2392
2431
  };
2393
2432
  function calculateImpact(score, weight, effort) {
@@ -2509,7 +2548,7 @@ function generatePitchNumbers(score, rawData, scorecard) {
2509
2548
  const passing = scorecard.filter((s) => s.score >= 7).length;
2510
2549
  metrics.push({
2511
2550
  metric: "Criteria Passing",
2512
- value: `${passing}/26`,
2551
+ value: `${passing}/28`,
2513
2552
  significance: passing >= 18 ? "Excellent coverage across AEO dimensions" : passing >= 12 ? "Good foundation with room to improve remaining criteria" : `${26 - passing} criteria need attention for full AI visibility`
2514
2553
  });
2515
2554
  return metrics;
@@ -2701,20 +2740,23 @@ async function fetchMultiPageData(siteData, options) {
2701
2740
 
2702
2741
  // src/page-scorer.ts
2703
2742
  var PAGE_CRITERIA = {
2704
- schema_markup: { weight: 0.15, label: "Schema.org Structured Data" },
2705
- qa_content_format: { weight: 0.15, label: "Q&A Content Format" },
2706
- clean_html: { weight: 0.1, label: "Clean, Crawlable HTML" },
2707
- faq_section: { weight: 0.1, label: "FAQ Section Content" },
2743
+ // Content Substance
2708
2744
  original_data: { weight: 0.1, label: "Original Data & Expert Content" },
2709
- query_answer_alignment: { weight: 0.08, label: "Query-Answer Alignment" },
2710
- content_freshness: { weight: 0.07, label: "Content Freshness Signals" },
2711
- table_list_extractability: { weight: 0.07, label: "Table & List Extractability" },
2712
- direct_answer_density: { weight: 0.07, label: "Direct Answer Paragraphs" },
2713
- semantic_html: { weight: 0.05, label: "Semantic HTML5 & Accessibility" },
2714
- fact_density: { weight: 0.05, label: "Fact & Data Density" },
2715
- definition_patterns: { weight: 0.04, label: "Definition Patterns" },
2716
- canonical_url: { weight: 0.04, label: "Canonical URL Strategy" },
2717
- visible_date_signal: { weight: 0.04, label: "Visible Date Signal" }
2745
+ fact_density: { weight: 0.06, label: "Fact & Data Density" },
2746
+ direct_answer_density: { weight: 0.05, label: "Direct Answer Paragraphs" },
2747
+ qa_content_format: { weight: 0.05, label: "Q&A Content Format" },
2748
+ query_answer_alignment: { weight: 0.05, label: "Query-Answer Alignment" },
2749
+ faq_section: { weight: 0.04, label: "FAQ Section Content" },
2750
+ // Content Organization
2751
+ content_freshness: { weight: 0.04, label: "Content Freshness Signals" },
2752
+ schema_markup: { weight: 0.03, label: "Schema.org Structured Data" },
2753
+ table_list_extractability: { weight: 0.03, label: "Table & List Extractability" },
2754
+ definition_patterns: { weight: 0.02, label: "Definition Patterns" },
2755
+ visible_date_signal: { weight: 0.02, label: "Visible Date Signal" },
2756
+ semantic_html: { weight: 0.02, label: "Semantic HTML5 & Accessibility" },
2757
+ clean_html: { weight: 0.02, label: "Clean, Crawlable HTML" },
2758
+ // Technical Plumbing
2759
+ canonical_url: { weight: 0.01, label: "Canonical URL Strategy" }
2718
2760
  };
2719
2761
  function extractJsonLdBlocks(html) {
2720
2762
  const blocks = [];
@@ -3484,32 +3526,37 @@ function buildLinkGraph(pages, domain, homepageUrl) {
3484
3526
 
3485
3527
  // src/fix-engine.ts
3486
3528
  var CRITERION_WEIGHTS2 = {
3487
- llms_txt: 0.1,
3488
- schema_markup: 0.15,
3489
- qa_content_format: 0.15,
3490
- clean_html: 0.1,
3491
- entity_consistency: 0.1,
3492
- robots_txt: 0.05,
3493
- faq_section: 0.1,
3529
+ // Content Substance (~55%)
3530
+ topic_coherence: 0.14,
3494
3531
  original_data: 0.1,
3495
- internal_linking: 0.1,
3496
- semantic_html: 0.05,
3497
- content_freshness: 0.07,
3498
- sitemap_completeness: 0.05,
3499
- rss_feed: 0.03,
3500
- table_list_extractability: 0.07,
3501
- definition_patterns: 0.04,
3502
- direct_answer_density: 0.07,
3503
- content_licensing: 0.04,
3504
- author_schema_depth: 0.04,
3505
- fact_density: 0.05,
3506
- canonical_url: 0.04,
3507
- content_velocity: 0.03,
3508
- schema_coverage: 0.03,
3509
- speakable_schema: 0.03,
3510
- query_answer_alignment: 0.08,
3511
- content_cannibalization: 0.05,
3512
- visible_date_signal: 0.04
3532
+ content_depth: 0.07,
3533
+ fact_density: 0.06,
3534
+ direct_answer_density: 0.05,
3535
+ qa_content_format: 0.05,
3536
+ query_answer_alignment: 0.05,
3537
+ faq_section: 0.04,
3538
+ // Content Organization (~30%)
3539
+ entity_consistency: 0.05,
3540
+ internal_linking: 0.04,
3541
+ content_freshness: 0.04,
3542
+ schema_markup: 0.03,
3543
+ author_schema_depth: 0.03,
3544
+ table_list_extractability: 0.03,
3545
+ definition_patterns: 0.02,
3546
+ visible_date_signal: 0.02,
3547
+ semantic_html: 0.02,
3548
+ clean_html: 0.02,
3549
+ // Technical Plumbing (~15%)
3550
+ content_cannibalization: 0.02,
3551
+ llms_txt: 0.02,
3552
+ robots_txt: 0.02,
3553
+ content_velocity: 0.02,
3554
+ content_licensing: 0.02,
3555
+ sitemap_completeness: 0.01,
3556
+ canonical_url: 0.01,
3557
+ rss_feed: 0.01,
3558
+ schema_coverage: 0.01,
3559
+ speakable_schema: 0.01
3513
3560
  };
3514
3561
  var PHASE_CONFIG = [
3515
3562
  {
@@ -3532,7 +3579,9 @@ var PHASE_CONFIG = [
3532
3579
  "content_freshness",
3533
3580
  "table_list_extractability",
3534
3581
  "query_answer_alignment",
3535
- "visible_date_signal"
3582
+ "visible_date_signal",
3583
+ "topic_coherence",
3584
+ "content_depth"
3536
3585
  ]
3537
3586
  },
3538
3587
  {
@@ -4436,6 +4485,55 @@ Summarization: yes`,
4436
4485
  affectedPages: affected,
4437
4486
  pageCount: affected?.length
4438
4487
  }];
4488
+ },
4489
+ topic_coherence: (c) => {
4490
+ if (c.score >= 10) return [];
4491
+ const impact = impactFromScore(c.score);
4492
+ const effort = effortForCriterion("topic_coherence", c.score);
4493
+ return [{
4494
+ id: "fix-topic-coherence",
4495
+ criterion: c.criterion_label,
4496
+ criterionId: c.criterion,
4497
+ title: "Focus blog content on core expertise",
4498
+ description: "Ensure blog content consistently covers your core topic areas. Scattered content across unrelated topics weakens AI engine authority signals.",
4499
+ impact,
4500
+ effort: effort === "trivial" ? "low" : effort,
4501
+ impactScore: 0,
4502
+ category: "content",
4503
+ steps: [
4504
+ "Identify 2-3 core expertise areas your brand is known for",
4505
+ "Audit existing blog posts and remove or consolidate off-topic content",
4506
+ "Create a content calendar focused on core topics",
4507
+ "Use topic clusters: pillar pages linking to supporting articles within the same niche"
4508
+ ],
4509
+ successCriteria: "80%+ of blog content covers core expertise areas with consistent topic focus"
4510
+ }];
4511
+ },
4512
+ content_depth: (c, pages) => {
4513
+ if (c.score >= 10) return [];
4514
+ const impact = impactFromScore(c.score);
4515
+ const effort = effortForCriterion("content_depth", c.score);
4516
+ const affected = getAffectedPages("content_depth", pages);
4517
+ return [{
4518
+ id: "fix-content-depth",
4519
+ criterion: c.criterion_label,
4520
+ criterionId: c.criterion,
4521
+ title: "Increase content depth and structure",
4522
+ description: "Expand thin content with more detail, examples, and structured sections. AI engines prefer comprehensive articles with clear heading hierarchies.",
4523
+ impact,
4524
+ effort: effort === "trivial" ? "low" : effort,
4525
+ impactScore: 0,
4526
+ category: "content",
4527
+ steps: [
4528
+ "Aim for 1000+ words per article with expert analysis and examples",
4529
+ "Use H2/H3 subheadings every 200-300 words for clear structure",
4530
+ "Add comparison tables, numbered steps, and data points",
4531
+ "Remove or expand thin pages (under 300 words) that dilute site quality"
4532
+ ],
4533
+ successCriteria: "Average article length exceeds 1000 words with 5+ subheadings per page",
4534
+ affectedPages: affected,
4535
+ pageCount: affected?.length
4536
+ }];
4439
4537
  }
4440
4538
  };
4441
4539
  function generateFixPlan(domain, overallScore, criteria, pagesReviewed, linkGraph) {