AINode.jsAutomation
SEO Content Analyzer with AI Scoring
TT
TopicTrick Team
SEO Content Analyzer with AI Scoring
Most SEO tools give you a score and a checklist. This tool gives you a contextual analysis — GPT-4o reads your actual content and tells you specifically what to rewrite, what to add, and what to fix, ranked by SEO impact.
This is Tool 10 of the Build 50 AI Automation Tools course.
What You'll Build
POST /analyze— provide a URL, receive a full SEO audit with scores and recommendations- Checks 15+ on-page SEO factors
- Returns prioritized action items with specific rewrites suggested
Setup
bash
mkdir seo-analyzer && cd seo-analyzer
npm init -y
npm install express axios cheerio openai dotenvbash
# .env
OPENAI_API_KEY=sk-your-key-here
PORT=3000SEO Analysis Service
js
// src/services/seoService.js
import axios from 'axios';
import * as cheerio from 'cheerio';
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
async function fetchPage(url) {
const { data, headers } = await axios.get(url, {
timeout: 15_000,
headers: { 'User-Agent': 'Mozilla/5.0 (compatible; SEOBot/1.0)' },
maxRedirects: 5,
});
return { html: data, contentType: headers['content-type'] || '' };
}
function extractSEOSignals(url, html) {
const $ = cheerio.load(html);
const title = $('title').first().text().trim();
const metaDescription = $('meta[name="description"]').attr('content') || '';
const h1 = $('h1').first().text().trim();
const h2s = $('h2').map((_, el) => $(el).text().trim()).get();
const h3s = $('h3').map((_, el) => $(el).text().trim()).get();
const bodyText = $('body').text().replace(/\s+/g, ' ').trim();
const wordCount = bodyText.split(/\s+/).length;
const imgAltMissing = $('img').filter((_, el) => !$(el).attr('alt')).length;
const imgTotal = $('img').length;
const internalLinks = $('a[href]').filter((_, el) => {
const href = $(el).attr('href') || '';
return href.startsWith('/') || href.includes(new URL(url).hostname);
}).length;
const externalLinks = $('a[href]').filter((_, el) => {
const href = $(el).attr('href') || '';
return href.startsWith('http') && !href.includes(new URL(url).hostname);
}).length;
const hasJsonLd = $('script[type="application/ld+json"]').length > 0;
const canonical = $('link[rel="canonical"]').attr('href') || null;
const robotsMeta = $('meta[name="robots"]').attr('content') || null;
return {
url,
title,
titleLength: title.length,
metaDescription,
metaDescriptionLength: metaDescription.length,
h1,
h2Count: h2s.length,
h3Count: h3s.length,
h2Headings: h2s.slice(0, 5),
wordCount,
bodyPreview: bodyText.slice(0, 1000),
imgTotal,
imgAltMissing,
internalLinks,
externalLinks,
hasStructuredData: hasJsonLd,
canonical,
robotsMeta,
};
}
export async function analyzeSEO(url, targetKeyword = null) {
const { html } = await fetchPage(url);
const signals = extractSEOSignals(url, html);
const keywordContext = targetKeyword ? `Target keyword: "${targetKeyword}"` : 'No specific target keyword provided — analyze general SEO quality.';
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: `You are a senior SEO specialist. Analyze the on-page SEO signals and provide a detailed audit.
${keywordContext}
Return ONLY a JSON object — no markdown:
{
"overallScore": 0-100,
"grade": "A | B | C | D | F",
"summary": "2-3 sentence executive summary",
"strengths": ["list of what is done well"],
"issues": [
{
"issue": "string — specific problem",
"impact": "high | medium | low",
"currentState": "string",
"recommendation": "string — specific action to take",
"exampleRewrite": "string or null — suggested new version of title/meta/heading if applicable"
}
],
"quickWins": ["top 3 things to fix immediately for the biggest SEO gain"],
"scores": {
"title": 0-10,
"metaDescription": 0-10,
"headings": 0-10,
"content": 0-10,
"images": 0-10,
"links": 0-10,
"technicalSEO": 0-10
}
}`,
},
{
role: 'user',
content: `Page signals:\n${JSON.stringify(signals, null, 2)}`,
},
],
temperature: 0.3,
response_format: { type: 'json_object' },
});
return { signals, audit: JSON.parse(response.choices[0].message.content) };
}API Route + Server
js
// src/server.js
import 'dotenv/config';
import express from 'express';
import { analyzeSEO } from './services/seoService.js';
const app = express();
app.use(express.json());
app.post('/analyze', async (req, res, next) => {
try {
const { url, keyword } = req.body;
if (!url) return res.status(400).json({ error: 'url is required' });
const result = await analyzeSEO(url, keyword);
res.json({ success: true, ...result });
} catch (err) { next(err); }
});
// Batch analysis
app.post('/analyze/batch', async (req, res, next) => {
try {
const { urls, keyword } = req.body;
if (!urls?.length) return res.status(400).json({ error: 'urls array required' });
const results = await Promise.allSettled(urls.map(url => analyzeSEO(url, keyword)));
res.json({
success: true,
results: results.map((r, i) =>
r.status === 'fulfilled' ? { url: urls[i], ...r.value } : { url: urls[i], error: r.reason.message }
),
});
} catch (err) { next(err); }
});
app.use((err, _req, res, _next) => res.status(500).json({ error: err.message }));
app.listen(process.env.PORT ?? 3000, () => console.log('SEO Analyzer running'));Testing
bash
curl -X POST http://localhost:3000/analyze \
-H "Content-Type: application/json" \
-d '{"url": "https://yourblog.com/article", "keyword": "nodejs tutorial"}'Sample response:
json
{
"audit": {
"overallScore": 62,
"grade": "C",
"summary": "The page has solid content depth but suffers from a weak title tag, missing meta description, and 8 images without alt text. Fixing these three issues alone could improve rankings significantly.",
"quickWins": [
"Rewrite title to include 'Node.js Tutorial' within first 30 characters",
"Add a 155-character meta description with target keyword",
"Add alt text to all 8 images"
],
"issues": [
{
"issue": "Title tag does not contain target keyword",
"impact": "high",
"currentState": "Getting Started with Backend Development",
"recommendation": "Include 'Node.js Tutorial' near the start of the title",
"exampleRewrite": "Node.js Tutorial: Complete Guide to Backend Development (2026)"
},
{
"issue": "Meta description is missing",
"impact": "high",
"currentState": "No meta description found",
"recommendation": "Write a 150-160 character description with target keyword and clear value proposition",
"exampleRewrite": "Learn Node.js from scratch in this comprehensive tutorial. Build REST APIs, handle databases, and deploy to production — step by step with real code examples."
}
]
}
}Build 50 AI Automation Tools — Tool 10 of 50
SEO analysis is live. Continue to Tool 11 to build an AI competitor research automation tool.
Summary
- Cheerio parses HTML server-side and extracts 15+ SEO signals without a browser
- AI analysis provides context-aware recommendations — not just rule-based warnings
- Specific rewrites tell you exactly what to change, not just what is wrong
- Score breakdown makes it easy to prioritize which SEO area needs the most attention
- Extend with Lighthouse integration for Core Web Vitals and technical performance scoring
Continue to Tool 11: Competitor Research Automation →
Post Navigation (Previous/Next)
