aeorank 1.4.0 → 1.6.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 +185 -2
- package/dist/browser.d.ts +524 -0
- package/dist/browser.js +4519 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.js +369 -9
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1691 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +181 -19
- package/dist/index.d.ts +181 -19
- package/dist/index.js +1680 -8
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -125,7 +125,7 @@ Run a complete audit. Returns `AuditResult` with:
|
|
|
125
125
|
- `pitchNumbers` - Key metrics (schema types, AI crawler access, etc.)
|
|
126
126
|
- `verdict` - Human-readable summary paragraph
|
|
127
127
|
- `bottomLine` - Actionable recommendation
|
|
128
|
-
- `pagesReviewed` - Per-page analysis with issues and
|
|
128
|
+
- `pagesReviewed` - Per-page analysis with issues, strengths, and AEO score (0-100)
|
|
129
129
|
- `elapsed` - Wall-clock seconds
|
|
130
130
|
|
|
131
131
|
**Options:**
|
|
@@ -139,6 +139,66 @@ Run a complete audit. Returns `AuditResult` with:
|
|
|
139
139
|
| `maxPages` | `number` | `200` | Max pages for full crawl |
|
|
140
140
|
| `concurrency` | `number` | `5` | Parallel fetches for full crawl |
|
|
141
141
|
|
|
142
|
+
### `scorePage(html, url?)`
|
|
143
|
+
|
|
144
|
+
Score a single HTML page against 14 per-page AEO criteria. Returns `PageScoreResult` with:
|
|
145
|
+
|
|
146
|
+
- `aeoScore` - 0-100 weighted score
|
|
147
|
+
- `criterionScores` - 14 `PageCriterionScore` entries (criterion, score 0-10, weight)
|
|
148
|
+
|
|
149
|
+
### `scoreAllPages(siteData)`
|
|
150
|
+
|
|
151
|
+
Batch-score all pages (homepage + blogSample) from a `SiteData` object. Returns `PageScoreResult[]`.
|
|
152
|
+
|
|
153
|
+
### `buildLinkGraph(pages, domain, homepageUrl)`
|
|
154
|
+
|
|
155
|
+
Analyze internal linking structure from crawled pages. Returns `LinkGraph` with:
|
|
156
|
+
|
|
157
|
+
- `nodes` - Map of URL to `PageNode` (in/out degree, depth, pillar/hub/orphan flags)
|
|
158
|
+
- `edges` - Array of `LinkEdge` (from, to, anchor text)
|
|
159
|
+
- `stats` - `LinkGraphStats` (total pages, orphans, pillars, hubs, avg depth, clusters)
|
|
160
|
+
- `clusters` - `TopicCluster[]` (pillar URL, spoke URLs, cohesion score)
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import { crawlFullSite, prefetchSiteData, buildLinkGraph } from 'aeorank';
|
|
164
|
+
|
|
165
|
+
const siteData = await prefetchSiteData('example.com');
|
|
166
|
+
const crawl = await crawlFullSite(siteData, { maxPages: 200 });
|
|
167
|
+
const graph = buildLinkGraph(crawl.pages, 'example.com', 'https://example.com');
|
|
168
|
+
|
|
169
|
+
console.log(graph.stats.orphanPages); // Pages with no inbound links
|
|
170
|
+
console.log(graph.stats.pillarPages); // High-authority hub pages
|
|
171
|
+
console.log(graph.clusters); // Topic clusters detected
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### `generateFixPlan(domain, score, criteria, pages?, linkGraph?)`
|
|
175
|
+
|
|
176
|
+
Generate a phased fix plan from audit results. Returns `FixPlan` with:
|
|
177
|
+
|
|
178
|
+
- `phases` - 4 phases (Foundation, Content, Authority, Architecture) with prioritized `FixAction[]`
|
|
179
|
+
- `quickWins` - Low-effort, high-impact fixes
|
|
180
|
+
- `projectedScore` - Estimated score after applying all fixes
|
|
181
|
+
- `summary` - Counts by impact level, top opportunity, estimated effort
|
|
182
|
+
|
|
183
|
+
Each `FixAction` includes: title, description, impact/effort levels, step-by-step instructions, code examples, affected pages, and dependency ordering.
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
import { audit, generateFixPlan } from 'aeorank';
|
|
187
|
+
|
|
188
|
+
const result = await audit('example.com');
|
|
189
|
+
const plan = generateFixPlan(
|
|
190
|
+
'example.com',
|
|
191
|
+
result.overallScore,
|
|
192
|
+
result.criterionResults,
|
|
193
|
+
result.pagesReviewed,
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
console.log(plan.projectedScore); // e.g. 82
|
|
197
|
+
console.log(plan.quickWins[0].title); // e.g. "Add llms.txt file"
|
|
198
|
+
console.log(plan.quickWins[0].impactScore); // e.g. 10
|
|
199
|
+
console.log(plan.phases[0].fixes.length); // Foundation phase fixes
|
|
200
|
+
```
|
|
201
|
+
|
|
142
202
|
### Advanced API
|
|
143
203
|
|
|
144
204
|
For custom pipelines, import individual stages:
|
|
@@ -152,6 +212,10 @@ import {
|
|
|
152
212
|
buildDetailedFindings,
|
|
153
213
|
generateVerdict,
|
|
154
214
|
generateOpportunities,
|
|
215
|
+
scorePage,
|
|
216
|
+
scoreAllPages,
|
|
217
|
+
buildLinkGraph,
|
|
218
|
+
generateFixPlan,
|
|
155
219
|
isSpaShell,
|
|
156
220
|
fetchWithHeadless,
|
|
157
221
|
} from 'aeorank';
|
|
@@ -161,6 +225,24 @@ const results = auditSiteFromData(siteData);
|
|
|
161
225
|
const score = calculateOverallScore(results);
|
|
162
226
|
```
|
|
163
227
|
|
|
228
|
+
### Browser Entry Point
|
|
229
|
+
|
|
230
|
+
For browser environments (Chrome extensions, web apps), import from `aeorank/browser` to avoid Node.js dependencies (Puppeteer, fs):
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
import {
|
|
234
|
+
prefetchSiteData,
|
|
235
|
+
auditSiteFromData,
|
|
236
|
+
calculateOverallScore,
|
|
237
|
+
buildLinkGraph,
|
|
238
|
+
generateFixPlan,
|
|
239
|
+
analyzeAllPages,
|
|
240
|
+
crawlFullSite,
|
|
241
|
+
} from 'aeorank/browser';
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
The browser entry exports everything except `headless-fetch` (Puppeteer), `html-report` (Node fs), `audit` orchestrator, and CLI.
|
|
245
|
+
|
|
164
246
|
## SPA Support
|
|
165
247
|
|
|
166
248
|
Sites that use client-side rendering (React, Vue, Angular) return empty HTML shells to regular HTTP requests. AEORank detects these automatically and re-renders them with Puppeteer if available.
|
|
@@ -208,6 +290,107 @@ console.log(crawlResult.pages.length); // Pages fetched
|
|
|
208
290
|
console.log(crawlResult.discoveredUrls.length); // Total URLs found
|
|
209
291
|
```
|
|
210
292
|
|
|
293
|
+
## Per-Page Scoring
|
|
294
|
+
|
|
295
|
+
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."
|
|
296
|
+
|
|
297
|
+
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.
|
|
298
|
+
|
|
299
|
+
The remaining 12 criteria (llms.txt, robots.txt, sitemap, RSS, entity consistency, internal linking, content licensing, author schema, content velocity, schema coverage, speakable schema, content cannibalization) are site-level only.
|
|
300
|
+
|
|
301
|
+
### CLI Output
|
|
302
|
+
|
|
303
|
+
Per-page scores appear in the pages section:
|
|
304
|
+
|
|
305
|
+
```
|
|
306
|
+
Pages reviewed (47):
|
|
307
|
+
Homepage https://example.com 0 issues [AEO: 72]
|
|
308
|
+
Blog https://example.com/blog/post 2 issues [AEO: 58]
|
|
309
|
+
|
|
310
|
+
Average page AEO score: 62/100
|
|
311
|
+
Top: /blog/medicare-walkers-guide (92)
|
|
312
|
+
Bottom: /thank-you (23)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Programmatic API
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
import { scorePage, scoreAllPages } from 'aeorank';
|
|
319
|
+
import type { PageScoreResult, PageCriterionScore } from 'aeorank';
|
|
320
|
+
|
|
321
|
+
// Score a single page
|
|
322
|
+
const result = scorePage(html, url);
|
|
323
|
+
console.log(result.aeoScore); // 0-100
|
|
324
|
+
console.log(result.criterionScores); // 14 per-criterion scores
|
|
325
|
+
|
|
326
|
+
// Score all pages from site data
|
|
327
|
+
const allScores = scoreAllPages(siteData);
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Link Graph Analysis
|
|
331
|
+
|
|
332
|
+
Analyze your site's internal linking structure to find orphan pages, identify pillar content, and detect topic clusters:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
npx aeorank example.com --full-crawl --json | jq '.linkGraph.stats'
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
```ts
|
|
339
|
+
import { crawlFullSite, prefetchSiteData, buildLinkGraph, serializeLinkGraph } from 'aeorank';
|
|
340
|
+
|
|
341
|
+
const siteData = await prefetchSiteData('example.com');
|
|
342
|
+
const crawl = await crawlFullSite(siteData, { maxPages: 200 });
|
|
343
|
+
const graph = buildLinkGraph(crawl.pages, 'example.com', 'https://example.com');
|
|
344
|
+
|
|
345
|
+
// Orphan pages (no inbound links - invisible to crawlers)
|
|
346
|
+
const orphans = [...graph.nodes.values()].filter(n => n.isOrphan);
|
|
347
|
+
|
|
348
|
+
// Pillar pages (high authority, many inbound links)
|
|
349
|
+
const pillars = [...graph.nodes.values()].filter(n => n.isPillar);
|
|
350
|
+
|
|
351
|
+
// Topic clusters (pillar + spoke pages with high cohesion)
|
|
352
|
+
graph.clusters.forEach(c => {
|
|
353
|
+
console.log(`${c.pillarTitle}: ${c.spokes.length} spokes, cohesion ${c.cohesion}`);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// Serialize for storage/transport (Map -> plain object)
|
|
357
|
+
const json = serializeLinkGraph(graph);
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Fix Plan Engine
|
|
361
|
+
|
|
362
|
+
Generate actionable, phased fix plans from audit results. Each fix includes step-by-step instructions, code examples, effort/impact ratings, and dependency ordering:
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
npx aeorank example.com --full-crawl --json | jq '.fixPlan'
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
import { audit, generateFixPlan } from 'aeorank';
|
|
370
|
+
|
|
371
|
+
const result = await audit('example.com', { fullCrawl: true });
|
|
372
|
+
const plan = generateFixPlan(
|
|
373
|
+
'example.com',
|
|
374
|
+
result.overallScore,
|
|
375
|
+
result.criterionResults,
|
|
376
|
+
result.pagesReviewed,
|
|
377
|
+
result.linkGraph, // optional - enables link-aware fixes
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
// 4 phases: Foundation -> Content -> Authority -> Architecture
|
|
381
|
+
plan.phases.forEach(phase => {
|
|
382
|
+
console.log(`${phase.title}: ${phase.fixes.length} fixes`);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// Quick wins: low effort + high impact
|
|
386
|
+
plan.quickWins.forEach(qw => {
|
|
387
|
+
console.log(`${qw.title} (+${qw.impactScore} pts) - ${qw.effort} effort`);
|
|
388
|
+
qw.steps.forEach(s => console.log(` - ${s}`));
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
console.log(`Current: ${plan.overallScore} -> Projected: ${plan.projectedScore}`);
|
|
392
|
+
```
|
|
393
|
+
|
|
211
394
|
## Scoring
|
|
212
395
|
|
|
213
396
|
Each criterion is scored 0-10 by deterministic checks (regex, HTML parsing, HTTP headers). The overall score is a weighted average normalized to 0-100.
|
|
@@ -266,7 +449,7 @@ console.log(result.comparison.tied); // Criteria with equal scores
|
|
|
266
449
|
|
|
267
450
|
## Benchmark Dataset
|
|
268
451
|
|
|
269
|
-
The `data/` directory contains the largest open dataset of AI visibility scores - **13,619 domains** scored across
|
|
452
|
+
The `data/` directory contains the largest open dataset of AI visibility scores - **13,619 domains** scored across 26 criteria, including **4,328 Y Combinator startups** across 48 batches (W06-W26):
|
|
270
453
|
|
|
271
454
|
| File | Contents |
|
|
272
455
|
|------|----------|
|