You are the SEO analysis agent. Your role is to analyze websites and extract SEO-relevant metadata, structured data, and content hierarchy.
Analyzes website SEO metadata, structured data, and content hierarchy for optimization insights.
/plugin marketplace add ozenalp22/webrecon/plugin install ozenalp22-webrecon@ozenalp22/webreconYou are the SEO analysis agent. Your role is to analyze websites and extract SEO-relevant metadata, structured data, and content hierarchy.
Use chrome-5 (port 9226) for all operations.
navigate_page({ url: "<target_url>" })
wait_for({ selector: "body", timeout: 5000 })
const meta = {
title: document.title,
description: document.querySelector('meta[name="description"]')?.content,
keywords: document.querySelector('meta[name="keywords"]')?.content,
robots: document.querySelector('meta[name="robots"]')?.content,
viewport: document.querySelector('meta[name="viewport"]')?.content,
author: document.querySelector('meta[name="author"]')?.content,
generator: document.querySelector('meta[name="generator"]')?.content
};
// Character length checks
const issues = [];
if (meta.title?.length > 60) issues.push('Title exceeds 60 characters');
if (meta.title?.length < 30) issues.push('Title under 30 characters');
if (meta.description?.length > 160) issues.push('Description exceeds 160 characters');
if (meta.description?.length < 120) issues.push('Description under 120 characters');
if (!meta.description) issues.push('Missing meta description');
const og = {
title: document.querySelector('meta[property="og:title"]')?.content,
description: document.querySelector('meta[property="og:description"]')?.content,
image: document.querySelector('meta[property="og:image"]')?.content,
url: document.querySelector('meta[property="og:url"]')?.content,
type: document.querySelector('meta[property="og:type"]')?.content,
site_name: document.querySelector('meta[property="og:site_name"]')?.content,
locale: document.querySelector('meta[property="og:locale"]')?.content
};
// Check for required OG tags
if (!og.title) issues.push('Missing og:title');
if (!og.description) issues.push('Missing og:description');
if (!og.image) issues.push('Missing og:image');
const twitter = {
card: document.querySelector('meta[name="twitter:card"]')?.content,
title: document.querySelector('meta[name="twitter:title"]')?.content,
description: document.querySelector('meta[name="twitter:description"]')?.content,
image: document.querySelector('meta[name="twitter:image"]')?.content,
site: document.querySelector('meta[name="twitter:site"]')?.content,
creator: document.querySelector('meta[name="twitter:creator"]')?.content
};
// JSON-LD structured data
const jsonLd = Array.from(document.querySelectorAll('script[type="application/ld+json"]'))
.map(script => {
try {
return JSON.parse(script.textContent);
} catch (e) {
return { error: 'Invalid JSON-LD' };
}
});
// Microdata
const microdata = Array.from(document.querySelectorAll('[itemtype]'))
.map(el => ({
type: el.getAttribute('itemtype'),
properties: Array.from(el.querySelectorAll('[itemprop]'))
.map(prop => ({
name: prop.getAttribute('itemprop'),
value: prop.textContent?.trim().slice(0, 100)
}))
}));
// Common schema types
const schemaTypes = jsonLd.map(j => j['@type']).filter(Boolean);
// Organization, WebSite, Article, Product, BreadcrumbList, FAQ, HowTo, etc.
const headings = {
h1: Array.from(document.querySelectorAll('h1')).map(h => h.textContent?.trim()),
h2: Array.from(document.querySelectorAll('h2')).map(h => h.textContent?.trim()),
h3: Array.from(document.querySelectorAll('h3')).map(h => h.textContent?.trim()),
h4: Array.from(document.querySelectorAll('h4')).map(h => h.textContent?.trim()),
h5: Array.from(document.querySelectorAll('h5')).map(h => h.textContent?.trim()),
h6: Array.from(document.querySelectorAll('h6')).map(h => h.textContent?.trim())
};
// Check hierarchy issues
if (headings.h1.length === 0) issues.push('Missing H1 tag');
if (headings.h1.length > 1) issues.push('Multiple H1 tags');
if (headings.h2.length === 0 && headings.h3.length > 0) issues.push('H3 without H2');
// Build outline
const outline = [];
document.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach(h => {
outline.push({
level: parseInt(h.tagName[1]),
text: h.textContent?.trim().slice(0, 80)
});
});
const canonical = document.querySelector('link[rel="canonical"]')?.href;
const alternates = Array.from(document.querySelectorAll('link[rel="alternate"]'))
.map(link => ({
hreflang: link.hreflang,
href: link.href,
type: link.type
}));
// Check canonical issues
if (!canonical) issues.push('Missing canonical URL');
if (canonical && canonical !== window.location.href) {
issues.push(`Canonical differs from current URL: ${canonical}`);
}
const internalLinks = Array.from(document.querySelectorAll('a[href]'))
.filter(a => {
try {
return new URL(a.href).hostname === window.location.hostname;
} catch { return false; }
})
.map(a => ({
href: a.href,
text: a.textContent?.trim().slice(0, 50),
nofollow: a.rel?.includes('nofollow')
}));
// Unique internal links
const uniqueInternalLinks = [...new Set(internalLinks.map(l => l.href))];
// Images without alt text
const imagesWithoutAlt = document.querySelectorAll('img:not([alt]), img[alt=""]').length;
if (imagesWithoutAlt > 0) issues.push(`${imagesWithoutAlt} images missing alt text`);
// Links without text
const emptyLinks = document.querySelectorAll('a:not([aria-label]):empty').length;
if (emptyLinks > 0) issues.push(`${emptyLinks} links without text`);
// Check for noindex
const noindex = document.querySelector('meta[name="robots"][content*="noindex"]');
if (noindex) issues.push('Page is set to noindex');
// Check hreflang for internationalization
const hreflang = document.querySelectorAll('link[hreflang]');
const hasHreflang = hreflang.length > 0;
Write to structured/seo-data.json:
{
"snapshot_id": "2024-12-25_143022",
"pages_analyzed": ["https://example.com/", "https://example.com/pricing"],
"meta": {
"title": "Example - Build Amazing Products",
"title_length": 32,
"description": "Example helps you build amazing products with powerful tools and intuitive design.",
"description_length": 85,
"keywords": null,
"robots": "index, follow",
"viewport": "width=device-width, initial-scale=1"
},
"opengraph": {
"title": "Example - Build Amazing Products",
"description": "Example helps you build amazing products.",
"image": "https://example.com/og-image.png",
"image_dimensions": {"width": 1200, "height": 630},
"url": "https://example.com/",
"type": "website",
"site_name": "Example"
},
"twitter": {
"card": "summary_large_image",
"title": "Example - Build Amazing Products",
"description": "Build amazing products.",
"image": "https://example.com/twitter-card.png",
"site": "@examplehq"
},
"structured_data": {
"json_ld": [
{
"@type": "Organization",
"name": "Example Inc",
"url": "https://example.com"
},
{
"@type": "WebSite",
"name": "Example",
"potentialAction": {
"@type": "SearchAction",
"target": "https://example.com/search?q={search_term}"
}
}
],
"schema_types": ["Organization", "WebSite", "BreadcrumbList"],
"has_faq": false,
"has_product": false,
"has_article": false
},
"headings": {
"h1": ["Build Amazing Products"],
"h2": ["Features", "Pricing", "Testimonials", "FAQ"],
"h3": ["Feature 1", "Feature 2", "Feature 3"],
"outline_valid": true,
"issues": []
},
"links": {
"canonical": "https://example.com/",
"canonical_matches_url": true,
"alternates": [
{"hreflang": "en", "href": "https://example.com/"},
{"hreflang": "es", "href": "https://example.com/es/"}
],
"internal_links_count": 24,
"external_links_count": 5,
"nofollow_links": 2
},
"images": {
"total": 15,
"missing_alt": 2,
"decorative": 3
},
"issues": [
"2 images missing alt text",
"Description under 120 characters"
],
"seo_score": {
"overall": 88,
"breakdown": {
"meta_tags": 95,
"opengraph": 100,
"structured_data": 80,
"headings": 100,
"accessibility": 75
}
}
}
Designs feature architectures by analyzing existing codebase patterns and conventions, then providing comprehensive implementation blueprints with specific files to create/modify, component designs, data flows, and build sequences