SEOAnalyzer API
The SEOAnalyzer class is the main entry point for analyzing HTML pages.
Constructor
import { SEOAnalyzer } from '@capyseo/core';
const analyzer = new SEOAnalyzer(options?: AnalyzerOptions);
Options
interface AnalyzerOptions {
rules?: SEORule[]; // Custom rules (default: all 46 rules)
aiProvider?: string; // 'gemini' | 'openai' | 'anthropic' | 'ollama'
aiApiKey?: string; // API key (auto-detected from env)
aiModel?: string; // Model name
cache?: boolean; // Enable AI caching
cacheTTL?: number; // Cache lifetime in ms
liveChecks?: boolean; // Enable live HTTP checks (default: true)
lighthouse?: boolean; // Enable Lighthouse metrics (default: false)
strictMode?: boolean; // Throw on errors (default: false)
}
Examples
// Default (all rules, no AI)
const analyzer = new SEOAnalyzer();
// With AI
const analyzer = new SEOAnalyzer({
aiProvider: 'gemini',
aiApiKey: process.env.GEMINI_API_KEY,
});
// Minimal (fast, no network)
const analyzer = new SEOAnalyzer({
liveChecks: false,
});
// With Lighthouse
const analyzer = new SEOAnalyzer({
lighthouse: true,
});
Methods
analyzePage
Analyze a single HTML page.
async analyzePage(
html: string,
url: string,
headers?: Headers
): Promise<SEOReport>
Parameters:
html - HTML content to analyze
url - Page URL (for resolving relative links)
headers - Optional HTTP response headers (for security rules)
Returns: SEOReport
Example:
const html = await fetch('https://example.com').then(r => r.text());
const report = await analyzer.analyzePage(html, 'https://example.com');
console.log(report.score); // 85
console.log(report.issues); // [{...}, {...}]
analyzeSite
Analyze multiple pages with streaming results.
async *analyzeSite(
urls: string[],
fetcher: (url: string) => Promise<{ html: string; headers?: Headers }>
): AsyncGenerator<SEOReport>
Parameters:
urls - Array of URLs to analyze
fetcher - Function to fetch HTML for each URL
Yields: SEOReport for each page
Example:
const urls = ['/', '/about', '/contact'];
const fetcher = async (url) => {
const res = await fetch(`https://example.com${url}`);
return { html: await res.text(), headers: res.headers };
};
for await (const report of analyzer.analyzeSite(urls, fetcher)) {
console.log(`${report.url}: ${report.score}/100`);
}
addRule
Add a custom rule.
addRule(rule: SEORule): void
Example:
analyzer.addRule({
id: 'custom-check',
name: 'Custom Check',
description: 'My custom SEO check',
check: async ($, url, context) => {
const issues = [];
if (!$('meta[name="author"]').length) {
issues.push({
ruleId: 'custom-check',
severity: 'info',
message: 'Missing author meta tag',
});
}
return issues;
},
});
removeRule
Remove a rule by ID.
removeRule(ruleId: string): void
Example:
analyzer.removeRule('word-count');
analyzer.removeRule('readability');
getRules
Get all active rules.
Return Types
SEOReport
interface SEOReport {
url: string; // Page URL
timestamp: string; // ISO 8601 timestamp
score: number; // 0-100 score
issues: SEOIssue[]; // List of issues
metrics?: PerformanceMetrics; // Lighthouse data (if enabled)
}
SEOIssue
interface SEOIssue {
ruleId: string; // e.g., 'meta-title'
severity: 'error' | 'warning' | 'info';
message: string; // Human-readable message
element?: string; // CSS selector or HTML snippet
line?: number; // Line number in HTML
suggestion?: string; // How to fix
autofix?: { // Programmatic fix data
type: 'attribute' | 'content' | 'add' | 'remove';
selector: string;
attribute?: string;
value?: string;
};
}
PerformanceMetrics
interface PerformanceMetrics {
lcp?: number; // Largest Contentful Paint (ms)
cls?: number; // Cumulative Layout Shift
fcp?: number; // First Contentful Paint (ms)
ttfb?: number; // Time to First Byte (ms)
tbt?: number; // Total Blocking Time (ms)
performanceScore?: number; // 0-100
}
Error Handling
Default Behavior
Errors are added as issues, analysis continues:
const analyzer = new SEOAnalyzer();
const report = await analyzer.analyzePage(html, url);
// If a rule throws, it becomes an issue
Strict Mode
Errors are thrown immediately:
const analyzer = new SEOAnalyzer({ strictMode: true });
try {
const report = await analyzer.analyzePage(html, url);
} catch (error) {
console.error('Analysis failed:', error);
}
Full Example
import { SEOAnalyzer, consoleReporter } from '@capyseo/core';
async function analyzeMysite() {
const analyzer = new SEOAnalyzer({
aiProvider: 'gemini',
aiApiKey: process.env.GEMINI_API_KEY,
liveChecks: true,
});
// Remove noisy rules
analyzer.removeRule('readability');
analyzer.removeRule('word-count');
// Analyze pages
const urls = ['/', '/about', '/blog'];
const reports = [];
for (const path of urls) {
const url = `https://mysite.com${path}`;
const html = await fetch(url).then(r => r.text());
const report = await analyzer.analyzePage(html, url);
reports.push(report);
}
// Output
console.log(consoleReporter(reports));
// Check score
const avgScore = reports.reduce((sum, r) => sum + r.score, 0) / reports.length;
if (avgScore < 80) {
process.exit(1);
}
}
analyzeMysite();