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 +104 -35
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +197 -99
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +115 -73
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +197 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +197 -99
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -362,7 +362,7 @@ declare function analyzeAllPages(siteData: SiteData): PageReview[];
|
|
|
362
362
|
|
|
363
363
|
/**
|
|
364
364
|
* Per-page AEO scoring.
|
|
365
|
-
* Evaluates 14 of
|
|
365
|
+
* Evaluates 14 of 28 criteria that apply at individual page level.
|
|
366
366
|
* Produces a 0-100 AEO score per page.
|
|
367
367
|
*/
|
|
368
368
|
|
package/dist/index.d.ts
CHANGED
|
@@ -362,7 +362,7 @@ declare function analyzeAllPages(siteData: SiteData): PageReview[];
|
|
|
362
362
|
|
|
363
363
|
/**
|
|
364
364
|
* Per-page AEO scoring.
|
|
365
|
-
* Evaluates 14 of
|
|
365
|
+
* Evaluates 14 of 28 criteria that apply at individual page level.
|
|
366
366
|
* Produces a 0-100 AEO score per page.
|
|
367
367
|
*/
|
|
368
368
|
|
package/dist/index.js
CHANGED
|
@@ -2069,40 +2069,58 @@ function auditSiteFromData(data) {
|
|
|
2069
2069
|
|
|
2070
2070
|
// src/scoring.ts
|
|
2071
2071
|
var WEIGHTS = {
|
|
2072
|
-
// ───
|
|
2073
|
-
|
|
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
|
-
//
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
content_depth: 0.
|
|
2080
|
-
//
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
//
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
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
|
-
|
|
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/headless-fetch.ts
|
|
@@ -2332,32 +2356,37 @@ function buildDetailedFindings(results) {
|
|
|
2332
2356
|
|
|
2333
2357
|
// src/narrative-generator.ts
|
|
2334
2358
|
var CRITERION_WEIGHTS = {
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
qa_content_format: 0.15,
|
|
2338
|
-
clean_html: 0.1,
|
|
2339
|
-
entity_consistency: 0.1,
|
|
2340
|
-
robots_txt: 0.05,
|
|
2341
|
-
faq_section: 0.1,
|
|
2359
|
+
// Content Substance (~55%)
|
|
2360
|
+
topic_coherence: 0.14,
|
|
2342
2361
|
original_data: 0.1,
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2362
|
+
content_depth: 0.07,
|
|
2363
|
+
fact_density: 0.06,
|
|
2364
|
+
direct_answer_density: 0.05,
|
|
2365
|
+
qa_content_format: 0.05,
|
|
2366
|
+
query_answer_alignment: 0.05,
|
|
2367
|
+
faq_section: 0.04,
|
|
2368
|
+
// Content Organization (~30%)
|
|
2369
|
+
entity_consistency: 0.05,
|
|
2370
|
+
internal_linking: 0.04,
|
|
2371
|
+
content_freshness: 0.04,
|
|
2372
|
+
schema_markup: 0.03,
|
|
2373
|
+
author_schema_depth: 0.03,
|
|
2374
|
+
table_list_extractability: 0.03,
|
|
2375
|
+
definition_patterns: 0.02,
|
|
2376
|
+
visible_date_signal: 0.02,
|
|
2377
|
+
semantic_html: 0.02,
|
|
2378
|
+
clean_html: 0.02,
|
|
2379
|
+
// Technical Plumbing (~15%)
|
|
2380
|
+
content_cannibalization: 0.02,
|
|
2381
|
+
llms_txt: 0.02,
|
|
2382
|
+
robots_txt: 0.02,
|
|
2383
|
+
content_velocity: 0.02,
|
|
2384
|
+
content_licensing: 0.02,
|
|
2385
|
+
sitemap_completeness: 0.01,
|
|
2386
|
+
canonical_url: 0.01,
|
|
2387
|
+
rss_feed: 0.01,
|
|
2388
|
+
schema_coverage: 0.01,
|
|
2389
|
+
speakable_schema: 0.01
|
|
2361
2390
|
};
|
|
2362
2391
|
var OPPORTUNITY_TEMPLATES = {
|
|
2363
2392
|
llms_txt: {
|
|
@@ -2489,6 +2518,16 @@ var OPPORTUNITY_TEMPLATES = {
|
|
|
2489
2518
|
name: "Add Visible Date Signals",
|
|
2490
2519
|
effort: "Low",
|
|
2491
2520
|
description: "Display publication/modification dates visibly using <time> elements and add datePublished/dateModified to JSON-LD schema."
|
|
2521
|
+
},
|
|
2522
|
+
topic_coherence: {
|
|
2523
|
+
name: "Focus Content on Core Topics",
|
|
2524
|
+
effort: "High",
|
|
2525
|
+
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.'
|
|
2526
|
+
},
|
|
2527
|
+
content_depth: {
|
|
2528
|
+
name: "Increase Content Depth",
|
|
2529
|
+
effort: "Medium",
|
|
2530
|
+
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."
|
|
2492
2531
|
}
|
|
2493
2532
|
};
|
|
2494
2533
|
function calculateImpact(score, weight, effort) {
|
|
@@ -2610,7 +2649,7 @@ function generatePitchNumbers(score, rawData, scorecard) {
|
|
|
2610
2649
|
const passing = scorecard.filter((s) => s.score >= 7).length;
|
|
2611
2650
|
metrics.push({
|
|
2612
2651
|
metric: "Criteria Passing",
|
|
2613
|
-
value: `${passing}/
|
|
2652
|
+
value: `${passing}/28`,
|
|
2614
2653
|
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`
|
|
2615
2654
|
});
|
|
2616
2655
|
return metrics;
|
|
@@ -2802,20 +2841,23 @@ async function fetchMultiPageData(siteData, options) {
|
|
|
2802
2841
|
|
|
2803
2842
|
// src/page-scorer.ts
|
|
2804
2843
|
var PAGE_CRITERIA = {
|
|
2805
|
-
|
|
2806
|
-
qa_content_format: { weight: 0.15, label: "Q&A Content Format" },
|
|
2807
|
-
clean_html: { weight: 0.1, label: "Clean, Crawlable HTML" },
|
|
2808
|
-
faq_section: { weight: 0.1, label: "FAQ Section Content" },
|
|
2844
|
+
// Content Substance
|
|
2809
2845
|
original_data: { weight: 0.1, label: "Original Data & Expert Content" },
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2846
|
+
fact_density: { weight: 0.06, label: "Fact & Data Density" },
|
|
2847
|
+
direct_answer_density: { weight: 0.05, label: "Direct Answer Paragraphs" },
|
|
2848
|
+
qa_content_format: { weight: 0.05, label: "Q&A Content Format" },
|
|
2849
|
+
query_answer_alignment: { weight: 0.05, label: "Query-Answer Alignment" },
|
|
2850
|
+
faq_section: { weight: 0.04, label: "FAQ Section Content" },
|
|
2851
|
+
// Content Organization
|
|
2852
|
+
content_freshness: { weight: 0.04, label: "Content Freshness Signals" },
|
|
2853
|
+
schema_markup: { weight: 0.03, label: "Schema.org Structured Data" },
|
|
2854
|
+
table_list_extractability: { weight: 0.03, label: "Table & List Extractability" },
|
|
2855
|
+
definition_patterns: { weight: 0.02, label: "Definition Patterns" },
|
|
2856
|
+
visible_date_signal: { weight: 0.02, label: "Visible Date Signal" },
|
|
2857
|
+
semantic_html: { weight: 0.02, label: "Semantic HTML5 & Accessibility" },
|
|
2858
|
+
clean_html: { weight: 0.02, label: "Clean, Crawlable HTML" },
|
|
2859
|
+
// Technical Plumbing
|
|
2860
|
+
canonical_url: { weight: 0.01, label: "Canonical URL Strategy" }
|
|
2819
2861
|
};
|
|
2820
2862
|
function extractJsonLdBlocks(html) {
|
|
2821
2863
|
const blocks = [];
|
|
@@ -3667,32 +3709,37 @@ function buildLinkGraph(pages, domain, homepageUrl) {
|
|
|
3667
3709
|
|
|
3668
3710
|
// src/fix-engine.ts
|
|
3669
3711
|
var CRITERION_WEIGHTS2 = {
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
qa_content_format: 0.15,
|
|
3673
|
-
clean_html: 0.1,
|
|
3674
|
-
entity_consistency: 0.1,
|
|
3675
|
-
robots_txt: 0.05,
|
|
3676
|
-
faq_section: 0.1,
|
|
3712
|
+
// Content Substance (~55%)
|
|
3713
|
+
topic_coherence: 0.14,
|
|
3677
3714
|
original_data: 0.1,
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3715
|
+
content_depth: 0.07,
|
|
3716
|
+
fact_density: 0.06,
|
|
3717
|
+
direct_answer_density: 0.05,
|
|
3718
|
+
qa_content_format: 0.05,
|
|
3719
|
+
query_answer_alignment: 0.05,
|
|
3720
|
+
faq_section: 0.04,
|
|
3721
|
+
// Content Organization (~30%)
|
|
3722
|
+
entity_consistency: 0.05,
|
|
3723
|
+
internal_linking: 0.04,
|
|
3724
|
+
content_freshness: 0.04,
|
|
3725
|
+
schema_markup: 0.03,
|
|
3726
|
+
author_schema_depth: 0.03,
|
|
3727
|
+
table_list_extractability: 0.03,
|
|
3728
|
+
definition_patterns: 0.02,
|
|
3729
|
+
visible_date_signal: 0.02,
|
|
3730
|
+
semantic_html: 0.02,
|
|
3731
|
+
clean_html: 0.02,
|
|
3732
|
+
// Technical Plumbing (~15%)
|
|
3733
|
+
content_cannibalization: 0.02,
|
|
3734
|
+
llms_txt: 0.02,
|
|
3735
|
+
robots_txt: 0.02,
|
|
3736
|
+
content_velocity: 0.02,
|
|
3737
|
+
content_licensing: 0.02,
|
|
3738
|
+
sitemap_completeness: 0.01,
|
|
3739
|
+
canonical_url: 0.01,
|
|
3740
|
+
rss_feed: 0.01,
|
|
3741
|
+
schema_coverage: 0.01,
|
|
3742
|
+
speakable_schema: 0.01
|
|
3696
3743
|
};
|
|
3697
3744
|
var PHASE_CONFIG = [
|
|
3698
3745
|
{
|
|
@@ -3715,7 +3762,9 @@ var PHASE_CONFIG = [
|
|
|
3715
3762
|
"content_freshness",
|
|
3716
3763
|
"table_list_extractability",
|
|
3717
3764
|
"query_answer_alignment",
|
|
3718
|
-
"visible_date_signal"
|
|
3765
|
+
"visible_date_signal",
|
|
3766
|
+
"topic_coherence",
|
|
3767
|
+
"content_depth"
|
|
3719
3768
|
]
|
|
3720
3769
|
},
|
|
3721
3770
|
{
|
|
@@ -4619,6 +4668,55 @@ Summarization: yes`,
|
|
|
4619
4668
|
affectedPages: affected,
|
|
4620
4669
|
pageCount: affected?.length
|
|
4621
4670
|
}];
|
|
4671
|
+
},
|
|
4672
|
+
topic_coherence: (c) => {
|
|
4673
|
+
if (c.score >= 10) return [];
|
|
4674
|
+
const impact = impactFromScore(c.score);
|
|
4675
|
+
const effort = effortForCriterion("topic_coherence", c.score);
|
|
4676
|
+
return [{
|
|
4677
|
+
id: "fix-topic-coherence",
|
|
4678
|
+
criterion: c.criterion_label,
|
|
4679
|
+
criterionId: c.criterion,
|
|
4680
|
+
title: "Focus blog content on core expertise",
|
|
4681
|
+
description: "Ensure blog content consistently covers your core topic areas. Scattered content across unrelated topics weakens AI engine authority signals.",
|
|
4682
|
+
impact,
|
|
4683
|
+
effort: effort === "trivial" ? "low" : effort,
|
|
4684
|
+
impactScore: 0,
|
|
4685
|
+
category: "content",
|
|
4686
|
+
steps: [
|
|
4687
|
+
"Identify 2-3 core expertise areas your brand is known for",
|
|
4688
|
+
"Audit existing blog posts and remove or consolidate off-topic content",
|
|
4689
|
+
"Create a content calendar focused on core topics",
|
|
4690
|
+
"Use topic clusters: pillar pages linking to supporting articles within the same niche"
|
|
4691
|
+
],
|
|
4692
|
+
successCriteria: "80%+ of blog content covers core expertise areas with consistent topic focus"
|
|
4693
|
+
}];
|
|
4694
|
+
},
|
|
4695
|
+
content_depth: (c, pages) => {
|
|
4696
|
+
if (c.score >= 10) return [];
|
|
4697
|
+
const impact = impactFromScore(c.score);
|
|
4698
|
+
const effort = effortForCriterion("content_depth", c.score);
|
|
4699
|
+
const affected = getAffectedPages("content_depth", pages);
|
|
4700
|
+
return [{
|
|
4701
|
+
id: "fix-content-depth",
|
|
4702
|
+
criterion: c.criterion_label,
|
|
4703
|
+
criterionId: c.criterion,
|
|
4704
|
+
title: "Increase content depth and structure",
|
|
4705
|
+
description: "Expand thin content with more detail, examples, and structured sections. AI engines prefer comprehensive articles with clear heading hierarchies.",
|
|
4706
|
+
impact,
|
|
4707
|
+
effort: effort === "trivial" ? "low" : effort,
|
|
4708
|
+
impactScore: 0,
|
|
4709
|
+
category: "content",
|
|
4710
|
+
steps: [
|
|
4711
|
+
"Aim for 1000+ words per article with expert analysis and examples",
|
|
4712
|
+
"Use H2/H3 subheadings every 200-300 words for clear structure",
|
|
4713
|
+
"Add comparison tables, numbered steps, and data points",
|
|
4714
|
+
"Remove or expand thin pages (under 300 words) that dilute site quality"
|
|
4715
|
+
],
|
|
4716
|
+
successCriteria: "Average article length exceeds 1000 words with 5+ subheadings per page",
|
|
4717
|
+
affectedPages: affected,
|
|
4718
|
+
pageCount: affected?.length
|
|
4719
|
+
}];
|
|
4622
4720
|
}
|
|
4623
4721
|
};
|
|
4624
4722
|
function generateFixPlan(domain, overallScore, criteria, pagesReviewed, linkGraph) {
|