SEOAnalyzer API

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.

getRules(): SEORule[]

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();