aeo-lens
v1.0.0
Published
AI Engine Optimization (AEO) analyzer - Analyze web content for AI readability, citation potential, and schema optimization
Downloads
29
Maintainers
Readme
What is AEO?
AI Engine Optimization (AEO) is the practice of optimizing content so that AI systems (like ChatGPT, Perplexity, Claude, Google AI Overviews) can easily understand, cite, and reference your content. As AI-powered search becomes mainstream, AEO is becoming as important as traditional SEO.
Installation
npm install aeo-lensOr use directly with npx (no installation required):
npx aeo-lens https://example.comThree Ways to Use AEO-Lens
1. 📦 As a Library (Programmatic)
Import into your backend, CMS, or build pipeline:
import { aeoAudit, extractFromText } from 'aeo-lens';
// When a writer saves a blog post in your CMS
const content = extractFromText(blogPostContent);
const audit = aeoAudit(content);
if (audit.hallucinationRisk > 50) {
throw new Error('Content has high hallucination risk - needs review');
}
if (audit.overallScore < 60) {
return { status: 'draft', issues: audit.actionableFixes };
}
// Access detailed analysis
console.log(audit.details.vagueClaims); // Vague words that need quantification
console.log(audit.details.ambiguity); // Ambiguous pronouns
console.log(audit.details.answerBlocks); // Self-contained answer blocks
console.log(audit.details.entities); // Named entities detected
console.log(audit.details.citeableSentence); // Best sentence for AI citation2. 🖥️ As a CLI Tool (Command Line)
Analyze any website or local file directly from your terminal:
# Analyze any URL (uses headless browser for JavaScript-rendered sites)
npx aeo-lens https://example.com/blog/article
# Analyze local files
npx aeo-lens ./my-content.md
npx aeo-lens ./article.html
npx aeo-lens ./blog-post.txt
# Get JSON output for scripting
npx aeo-lens https://example.com --json
# Set minimum score threshold (for CI/CD)
npx aeo-lens ./content.md --min-score 70
# Choose persona for analysis
npx aeo-lens https://example.com --persona technicalExample CLI Output:
╔═══════════════════════════════════════╗
║ � AEO-LENS v1.0.0 ║
║ AI Engine Optimization Analyzer ║
╚═══════════════════════════════════════╝
╔═══════════════════════════════════════╗
║ AEO SCORE: 65 ║
║ Grade: C ║
╚═══════════════════════════════════════╝
═══ QUICK STATS ═══
Words: 1250 │ FK Grade: 8.5 │ Headings: 6 │ Ext Links: 4 │ Data Pts: 8 │ Chunks: 3
═══ SCORE BREAKDOWN ═══
Trust Score ██████████████████░░░░░░░░░░░░ 58/100
Extractability ████████████████████████░░░░░░ 78/100
Structure ██████████████████████░░░░░░░░ 72/100
Hallucination Risk ██████░░░░░░░░░░░░░░░░░░░░░░░░ 20/100
═══ 🔍 RETRIEVABILITY SCORE ═══
██████████████████████████████░░░░░░░░░░ 75%
Status: CRAWLABLE
═══ 📋 SCHEMA "SPEAKING AI" VALIDATOR ═══
❓ FAQ Page ✓ DETECTED
📝 How-To ✗ MISSING
📰 Article ✓ DETECTED
🛍️ Product ✗ MISSING
⭐ Review ✗ MISSING
═══ 📦 SELF-CONTAINED CHUNKS AUDITOR ═══
3 citeable chunks found (target: 3+)
Chunks are H2/H3 sections with 90-120 word direct answers
═══ ⚠️ HALLUCINATION RISK METER ═══
LOW HIGH
──────▼───────────────────────────────
20% - LOW RISK
═══ 🔎 VAGUE CLAIMS DETECTOR ═══
3 vague terms found that may cause AI misinterpretation
1. "significant" in: "We saw significant improvements in conversion rates..."
→ Fix: Use specific numbers (e.g., "35% increase")
2. "many" in: "Many users reported better results after..."
→ Fix: Specify the quantity (e.g., "over 500 users")
═══ 🏷️ ENTITY OPTIMIZER ═══
HubSpot(8) SEO(6) Marketing(5) AI(4) Content(3)
Topic Cluster: marketing (70% match)
Missing keywords: engagement, campaign
═══ 💬 CITEABLE SNIPPET MOCK-UP ═══
┌─────────────────────────────────────────────────────────┐
│ "According to HubSpot research, companies that blog..." │
└─────────────────────────────────────────────────────────┘
Citeability: HIGH (score: 75)
═══ 🔧 ACTIONABLE FIXES ═══
1. Replace 3 vague terms with specific data
2. Add How-To schema markup
3. Create more self-contained answer blocks (90-120 words)3. 🔄 In CI/CD (Automation)
Add to your GitHub Actions, GitLab CI, or any build pipeline to ensure content quality:
# .github/workflows/aeo-check.yml
name: AEO Quality Check
on: [push, pull_request]
jobs:
aeo-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Run AEO Audit
run: npx aeo-lens ./content/**/*.md --min-score 70
# Fails the build if any content scores below 70Exit Codes:
| Code | Meaning |
|------|---------|
| 0 | Success - score meets minimum threshold |
| 1 | Failure - score below minimum threshold |
| 2 | Error - invalid input, network error, etc. |
Features
🎯 Hallucination Risk Engine
Detects content patterns that may cause AI to misinterpret or hallucinate information.
import { detectAmbiguity, detectVagueClaims } from 'aeo-lens';
// Detect dangling pronouns (>15 words from proper noun)
const ambiguity = detectAmbiguity('The system processes data. After several steps, it sends results.');
// Flags "it" as ambiguous - too far from "system"
// Detect vague claims without quantification
const vague = detectVagueClaims('Many users saw significant improvements.');
// Flags: "many" → "Specify the quantity (e.g., over 500 users)"
// Flags: "significant" → "Use specific numbers (e.g., 35% increase)"📊 Citation Probability Scorer
Identifies content with high citation potential based on claim-evidence structure.
import { scoreClaimEvidence } from 'aeo-lens';
const result = scoreClaimEvidence(content);
// Rewards: numerical stat + declarative verb + external link/citation
// { wellSupportedCount: 5, totalClaims: 8, score: 75 }📦 AI Chunking Auditor
Checks for self-contained answer blocks that AI can easily extract.
import { auditAnswerBlocks } from 'aeo-lens';
const chunks = auditAnswerBlocks(content);
// Optimal: H2/H3 header + direct answer (90-120 words) with key entities
// { optimalBlocks: 3, totalBlocks: 8, score: 65 }🤖 Bot-Blocker Check
Validates robots.txt permissions for AI crawlers.
import { validateRobotsTxt } from 'aeo-lens';
const robots = await validateRobotsTxt('https://example.com');
console.log(robots.aiBots);
// [
// { bot: 'GPTBot', allowed: true },
// { bot: 'ClaudeBot', allowed: false },
// { bot: 'Google-Extended', allowed: true }
// ]
console.log(robots.hasLlmsTxt); // false
// Recommendation: "Add llms.txt file for LLM-specific instructions"📝 Answer-First Grading
Ensures key information isn't buried where AI might miss it.
import { gradeAnswerFirst } from 'aeo-lens';
const result = gradeAnswerFirst(content);
// {
// answerPosition: 'first' | 'second' | 'buried' | 'not-found',
// score: 85,
// keyInfoInLead: ['data/statistics', 'direct answer'],
// recommendations: []
// }🏷️ Entity & Topic Detection
Identifies named entities and matches content to topic clusters.
import { aeoAudit } from 'aeo-lens';
const audit = aeoAudit(content);
console.log(audit.details.entities);
// [{ entity: 'HubSpot', count: 8 }, { entity: 'SEO', count: 6 }]
console.log(audit.details.topicCluster);
// { cluster: 'marketing', score: 0.7, matches: ['seo', 'content'], missing: ['engagement'] }💬 Citeable Snippet Finder
Identifies the most AI-citeable sentence in your content.
import { aeoAudit } from 'aeo-lens';
const audit = aeoAudit(content);
console.log(audit.details.citeableSentence);
// {
// text: "According to HubSpot research, companies that blog get 55% more visitors.",
// score: 85,
// rating: 'HIGH'
// }API Reference
Main Functions
| Function | Description |
|----------|-------------|
| aeoAudit(content) | Main audit returning all scores and detailed analysis |
| aeoAuditWithRobots(content, url) | Full audit including robots.txt validation (async) |
| extractFromText(text, options?) | Extract structured content from plain text |
| extractFromHTML(html) | Extract structured content from HTML |
| analyzeText(text, options?) | Quick text analysis with AEOAnalyzer |
Analysis Functions
| Function | Description |
|----------|-------------|
| detectVagueClaims(text) | Find vague words without quantification |
| scoreClaimEvidence(content) | Score claim-evidence structure |
| auditAnswerBlocks(content) | Check for self-contained answer blocks |
| detectAmbiguity(text) | Find dangling pronouns |
| gradeAnswerFirst(content) | Check if answer is in first paragraph |
| validateRobotsTxt(url) | Check AI bot permissions (async) |
CLI Options
npx aeo-lens <url-or-file> [options]
Arguments:
<url-or-file> URL to analyze or path to local file (.txt, .html, .md)
Options:
--json Output results as JSON (for scripting)
--min-score <n> Exit with code 1 if score < n (for CI/CD)
--persona <p> Set analysis persona: consumer | technical | c-suite
--no-color Disable colored output
--help, -h Show help messageAEO Audit Result Structure
interface AEOAuditResult {
// Main Scores (0-100)
trustScore: number; // Citation probability
hallucinationRisk: number; // Risk of AI misinterpretation (lower is better)
extractability: number; // How easily AI can extract info
structureScore: number; // Content structure quality
overallScore: number; // Combined weighted score
// Recommendations
actionableFixes: string[]; // Specific improvements to make
// Detailed Analysis
details: {
vagueClaims: VagueClaimsResult; // Vague words needing quantification
claimEvidence: ClaimEvidenceResult; // Claim-evidence pairs
answerBlocks: AnswerBlocksResult; // Self-contained chunks
ambiguity: AmbiguityResult; // Dangling pronouns
// Additional metrics
wordCount: number;
fleschKincaid: number;
headingCount: number;
externalLinks: number;
dataPoints: number;
schemaTypes: string[];
hasFAQ: boolean;
entities: EntityCount[];
topicCluster: TopicClusterMatch | null;
citeableSentence: CiteableSentenceResult;
};
}Scoring Algorithm
AEO-Lens uses a weighted scoring algorithm:
| Component | Weight | What it Measures | |-----------|--------|------------------| | Trust Score | 30% | Citation probability based on evidence, links, specificity | | Hallucination Risk (inverted) | 25% | Ambiguous pronouns, vague claims, unsupported statements | | Extractability | 25% | Schema markup, FAQ sections, answer blocks | | Structure | 20% | Headings, lists, content organization |
Grade Scale: | Score | Grade | |-------|-------| | 80-100 | A | | 70-79 | B | | 60-69 | C | | 50-59 | D | | 0-49 | F |
Use Cases
CMS Integration
Block publishing if content quality is too low:
// Strapi/Sanity/WordPress plugin
const audit = aeoAudit(extractFromText(post.content));
if (audit.hallucinationRisk > 60) {
return { error: 'High hallucination risk - please review flagged sections' };
}
if (audit.overallScore < 50) {
return { warning: 'Content needs improvement', fixes: audit.actionableFixes };
}Content Auditing
Analyze existing content library:
import { aeoAudit, extractFromHTML } from 'aeo-lens';
import fs from 'fs';
const files = fs.readdirSync('./content');
const results = files.map(file => {
const html = fs.readFileSync(`./content/${file}`, 'utf-8');
const content = extractFromHTML(html);
return { file, audit: aeoAudit(content) };
});
// Sort by score to find content needing improvement
results.sort((a, b) => a.audit.overallScore - b.audit.overallScore);Real-time Writing Feedback
Provide feedback as users write:
// Debounced analysis on text change
const analyzeContent = debounce((text) => {
const content = extractFromText(text);
const audit = aeoAudit(content);
updateUI({
score: audit.overallScore,
issues: audit.details.vagueClaims.claims,
suggestions: audit.actionableFixes
});
}, 500);Requirements
- Node.js >= 16.0.0
- Chrome/Chromium (for CLI URL analysis - auto-detected)
For CLI URL analysis, AEO-Lens uses Puppeteer to render JavaScript-heavy sites. Chrome is automatically detected on:
- Windows:
C:\Program Files\Google\Chrome\Application\chrome.exe - macOS:
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome - Linux:
/usr/bin/google-chromeor/usr/bin/chromium
Troubleshooting
CLI can't fetch a website
Some websites block automated requests. Workarounds:
- Save the page locally (Ctrl+S in browser) and analyze the HTML file
- Copy the article text to a .txt file and analyze that
- Use the library programmatically with your own fetching logic
Low scores on JavaScript-heavy sites
The CLI uses a headless browser, but some sites may still not render fully. For best results with SPAs, save the rendered page locally.
License
MIT © Aryan Patankar
