jason1i's picture
Add 2 files
01fb2c4 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SEO Analyzer Tool</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary-color: #4a6fa5;
--secondary-color: #166088;
--accent-color: #4fc3f7;
--light-color: #f8f9fa;
--dark-color: #343a40;
--success-color: #28a745;
--warning-color: #ffc107;
--danger-color: #dc3545;
--border-radius: 8px;
--box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: #f5f7fa;
color: var(--dark-color);
line-height: 1.6;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
text-align: center;
margin-bottom: 40px;
padding: 20px 0;
background-color: white;
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
}
h1 {
color: var(--primary-color);
margin-bottom: 10px;
font-weight: 700;
}
.tagline {
color: var(--secondary-color);
font-size: 1.2rem;
margin-bottom: 20px;
}
.analyzer-container {
display: flex;
flex-direction: column;
gap: 20px;
}
.input-section, .results-section {
background-color: white;
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
padding: 25px;
}
.input-section {
display: flex;
flex-direction: column;
gap: 15px;
}
.input-group {
display: flex;
flex-direction: column;
gap: 5px;
}
label {
font-weight: 600;
color: var(--secondary-color);
}
input[type="url"], textarea {
padding: 12px 15px;
border: 1px solid #ddd;
border-radius: var(--border-radius);
font-size: 1rem;
transition: all 0.3s;
}
input[type="url"]:focus, textarea:focus {
outline: none;
border-color: var(--accent-color);
box-shadow: 0 0 0 2px rgba(79, 195, 247, 0.2);
}
.button-group {
display: flex;
gap: 10px;
}
button {
padding: 12px 20px;
border: none;
border-radius: var(--border-radius);
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 8px;
}
.btn-primary {
background-color: var(--primary-color);
color: white;
}
.btn-primary:hover {
background-color: var(--secondary-color);
}
.btn-secondary {
background-color: var(--light-color);
color: var(--dark-color);
border: 1px solid #ddd;
}
.btn-secondary:hover {
background-color: #e9ecef;
}
.results-section {
display: none;
}
.results-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
.results-header h2 {
color: var(--primary-color);
}
.overall-score {
font-size: 1.5rem;
font-weight: 700;
color: white;
background-color: var(--primary-color);
padding: 8px 15px;
border-radius: var(--border-radius);
}
.results-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.result-card {
background-color: var(--light-color);
border-radius: var(--border-radius);
padding: 20px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
transition: transform 0.3s;
}
.result-card:hover {
transform: translateY(-5px);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.card-title {
font-weight: 600;
color: var(--secondary-color);
display: flex;
align-items: center;
gap: 8px;
}
.card-icon {
font-size: 1.2rem;
}
.card-status {
padding: 4px 10px;
border-radius: 20px;
font-size: 0.8rem;
font-weight: 600;
}
.status-good {
background-color: rgba(40, 167, 69, 0.2);
color: var(--success-color);
}
.status-warning {
background-color: rgba(255, 193, 7, 0.2);
color: var(--warning-color);
}
.status-bad {
background-color: rgba(220, 53, 69, 0.2);
color: var(--danger-color);
}
.result-details {
margin-top: 10px;
color: #555;
font-size: 0.95rem;
}
.keyword-density-list {
list-style-type: none;
margin-top: 10px;
}
.keyword-density-list li {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-bottom: 1px dashed #eee;
}
.progress-bar {
background-color: #e9ecef;
height: 10px;
border-radius: 5px;
margin-top: 15px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: var(--primary-color);
border-radius: 5px;
transition: width 0.5s;
}
.issues-list {
margin-top: 10px;
list-style-type: none;
}
.issues-list li {
padding: 5px 0;
display: flex;
align-items: flex-start;
gap: 8px;
}
.issue-icon {
color: var(--danger-color);
margin-top: 3px;
}
.toggle-details {
color: var(--accent-color);
cursor: pointer;
font-weight: 600;
margin-top: 10px;
display: inline-block;
}
.details-content {
display: none;
background-color: white;
padding: 15px;
margin-top: 10px;
border-radius: var(--border-radius);
border-left: 3px solid var(--accent-color);
font-family: monospace;
white-space: pre-wrap;
word-break: break-word;
max-height: 200px;
overflow-y: auto;
}
.active .details-content {
display: block;
}
footer {
text-align: center;
margin-top: 40px;
padding: 20px;
color: #666;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.results-content {
grid-template-columns: 1fr;
}
.button-group {
flex-direction: column;
}
}
/* Loading spinner */
.loader {
display: none;
border: 4px solid rgba(0, 0, 0, 0.1);
border-radius: 50%;
border-top: 4px solid var(--primary-color);
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 20px auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="container">
<header>
<h1><i class="fas fa-search"></i> SEO Analyzer Tool</h1>
<p class="tagline">Optimize your website's search engine performance with our comprehensive SEO analysis</p>
</header>
<div class="analyzer-container">
<div class="input-section">
<h2><i class="fas fa-chart-line"></i> Analyze Your Website</h2>
<p>Enter a URL or HTML content to analyze the SEO factors and get improvement suggestions.</p>
<div class="input-group">
<label for="url-input"><i class="fas fa-link"></i> Website URL</label>
<input type="url" id="url-input" placeholder="https://example.com" autocomplete="off">
</div>
<div class="input-group">
<label for="html-input"><i class="fas fa-code"></i> Or paste HTML content</label>
<textarea id="html-input" rows="8" placeholder="Paste your HTML content here..."></textarea>
</div>
<div class="input-group">
<label for="keywords-input"><i class="fas fa-key"></i> Target keywords (comma separated)</label>
<input type="text" id="keywords-input" placeholder="seo, analyzer, tool">
</div>
<div class="button-group">
<button class="btn-primary" id="analyze-btn">
<i class="fas fa-search"></i> Analyze SEO
</button>
<button class="btn-secondary" id="clear-btn">
<i class="fas fa-trash"></i> Clear
</button>
</div>
</div>
<div class="loader" id="loader"></div>
<div class="results-section" id="results-section">
<div class="results-header">
<h2><i class="fas fa-clipboard-check"></i> Analysis Results</h2>
<div class="overall-score" id="overall-score">0/100</div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="score-progress" style="width: 0%"></div>
</div>
<div class="results-content" id="results-content">
<!-- Results will be populated here by JavaScript -->
</div>
</div>
</div>
</div>
<footer>
<p>&copy; 2023 SEO Analyzer Tool | Built with HTML, CSS & JavaScript</p>
</footer>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const urlInput = document.getElementById('url-input');
const htmlInput = document.getElementById('html-input');
const keywordsInput = document.getElementById('keywords-input');
const analyzeBtn = document.getElementById('analyze-btn');
const clearBtn = document.getElementById('clear-btn');
const resultsSection = document.getElementById('results-section');
const resultsContent = document.getElementById('results-content');
const overallScore = document.getElementById('overall-score');
const scoreProgress = document.getElementById('score-progress');
const loader = document.getElementById('loader');
// Event Listeners
analyzeBtn.addEventListener('click', analyzeSEO);
clearBtn.addEventListener('click', clearInputs);
// Toggle details visibility
document.addEventListener('click', function(e) {
if (e.target.classList.contains('toggle-details')) {
e.target.parentElement.classList.toggle('active');
}
});
// Analyze SEO function
function analyzeSEO() {
const url = urlInput.value.trim();
const html = htmlInput.value.trim();
const keywords = keywordsInput.value.trim();
if (!url && !html) {
alert('Please enter a URL or paste HTML content to analyze.');
return;
}
// Show loading spinner
loader.style.display = 'block';
resultsSection.style.display = 'none';
// Simulate analysis (in a real app, you'd fetch data from a server or API)
setTimeout(() => {
const analysisResults = performAnalysis(url, html, keywords);
displayResults(analysisResults);
// Hide loading spinner and show results
loader.style.display = 'none';
resultsSection.style.display = 'block';
}, 1500);
}
// Perform SEO analysis
function performAnalysis(url, html, keywords) {
// Parse keywords
const targetKeywords = keywords
? keywords.split(',').map(k => k.trim().toLowerCase()).filter(k => k)
: [];
// For demo purposes, we'll simulate analysis results
// In a real app, you would parse the HTML and calculate these values
const hasTitle = Math.random() > 0.1;
const titleText = hasTitle ? 'SEO Analyzer Tool - Improve Your Search Rankings' : '';
const titleLength = hasTitle ? titleText.length : 0;
const hasMetaDescription = Math.random() > 0.2;
const metaDescriptionText = hasMetaDescription
? 'Free SEO analyzer tool that checks your website for common SEO issues and provides improvement suggestions.'
: '';
const metaDescriptionLength = hasMetaDescription ? metaDescriptionText.length : 0;
const hasH1 = Math.random() > 0.1;
const h1Count = hasH1 ? 1 : 0;
const h1Text = hasH1 ? 'SEO Analyzer Tool' : '';
const h2Count = Math.floor(Math.random() * 4) + (hasH1 ? 1 : 0);
const imageCount = Math.floor(Math.random() * 10) + 3;
const imagesWithAlt = Math.floor(Math.random() * (imageCount - 2)) + 1;
const linksCount = Math.floor(Math.random() * 20) + 5;
const internalLinksCount = Math.floor(linksCount * 0.7);
const externalLinksCount = linksCount - internalLinksCount;
const wordCount = Math.floor(Math.random() * 1500) + 500;
const keywordDensity = {};
targetKeywords.forEach(keyword => {
const density = Math.random() * 2 + 0.5;
keywordDensity[keyword] = parseFloat(density.toFixed(1));
});
// Calculate overall score (0-100)
const scoreFactors = {
title: hasTitle ? 10 : 0,
titleLength: titleLength >= 30 && titleLength <= 60 ? 5 : 0,
metaDescription: hasMetaDescription ? 10 : 0,
metaDescriptionLength: metaDescriptionLength >= 70 && metaDescriptionLength <= 160 ? 5 : 0,
h1: h1Count === 1 ? 10 : 0,
h2: h2Count >= 2 ? 5 : 0,
images: imagesWithAlt / imageCount * 5,
internalLinks: internalLinksCount >= 5 ? 5 : 0,
keywords: Object.keys(keywordDensity).length > 0 ? 5 : 0,
keywordDensity: targetKeywords.length > 0 ? 10 : 0
};
let score = 0;
for (const factor in scoreFactors) {
score += scoreFactors[factor];
}
score = Math.floor(score);
return {
url,
score,
targetKeywords,
details: {
title: {
exists: hasTitle,
text: titleText,
length: titleLength,
status: titleLength >= 30 && titleLength <= 60 ? 'good' : titleLength > 60 ? 'too-long' : 'too-short'
},
metaDescription: {
exists: hasMetaDescription,
text: metaDescriptionText,
length: metaDescriptionLength,
status: metaDescriptionLength >= 70 && metaDescriptionLength <= 160 ? 'good' : metaDescriptionLength > 160 ? 'too-long' : 'too-short'
},
headings: {
h1: {
exists: hasH1,
count: h1Count,
text: h1Text
},
h2: {
count: h2Count
}
},
images: {
count: imageCount,
withAlt: imagesWithAlt
},
links: {
count: linksCount,
internal: internalLinksCount,
external: externalLinksCount
},
content: {
wordCount: wordCount
},
keywordDensity: keywordDensity
}
};
}
// Display analysis results
function displayResults(results) {
// Update overall score
overallScore.textContent = `${results.score}/100`;
scoreProgress.style.width = `${results.score}%`;
// Empty results container
resultsContent.innerHTML = '';
// Add meta tags card
addResultCard({
title: 'Meta Tags',
icon: 'fas fa-tags',
status: results.details.title.exists && results.details.metaDescription.exists ? 'good' :
!results.details.title.exists && !results.details.metaDescription.exists ? 'bad' : 'warning',
content: [
results.details.title.exists
? `<p>Title tag: <strong>"${results.details.title.text}"</strong> (${results.details.title.length} chars)</p>
<p class="${results.details.title.status === 'good' ? 'status-good' : 'status-bad'}">
${results.details.title.status === 'good' ? '✓ Good length (30-60 characters)' :
results.details.title.status === 'too-long' ? '✗ Too long (over 60 characters)' : '✗ Too short (under 30 characters)'}
</p>`
: '<p class="status-bad">✗ Missing title tag</p>',
results.details.metaDescription.exists
? `<p>Meta description: <strong>"${results.details.metaDescription.text}"</strong> (${results.details.metaDescription.length} chars)</p>
<p class="${results.details.metaDescription.status === 'good' ? 'status-good' : 'status-bad'}">
${results.details.metaDescription.status === 'good' ? '✓ Good length (70-160 characters)' :
results.details.metaDescription.status === 'too-long' ? '✗ Too long (over 160 characters)' : '✗ Too short (under 70 characters)'}
</p>`
: '<p class="status-bad">✗ Missing meta description</p>',
`<span class="toggle-details">Show/hide details</span>
<div class="details-content">
Title: ${results.details.title.exists ? results.details.title.text : 'Not found'}
\nMeta Description: ${results.details.metaDescription.exists ? results.details.metaDescription.text : 'Not found'}
</div>`
].join('')
});
// Add headings card
addResultCard({
title: 'Headings',
icon: 'fas fa-heading',
status: results.details.headings.h1.exists && results.details.headings.h2.count >= 2 ? 'good' :
!results.details.headings.h1.exists ? 'bad' : 'warning',
content: [
results.details.headings.h1.exists
? `<p>H1: <strong>"${results.details.headings.h1.text}"</strong> (1 found)</p>`
: '<p class="status-bad">✗ No H1 heading found</p>',
`<p>H2: ${results.details.headings.h2.count} found</p>
<p class="${results.details.headings.h2.count >= 2 ? 'status-good' : 'status-warning'}">
${results.details.headings.h2.count >= 2 ? '✓ Good' : '⚠️ Consider adding more (2+ recommended)'}
</p>`,
`<span class="toggle-details">Show/hide details</span>
<div class="details-content">
H1 Count: ${results.details.headings.h1.exists ? '1' : '0'}
\nH2 Count: ${results.details.headings.h2.count}
</div>`
].join('')
});
// Add images card
const imagesPercentage = Math.round((results.details.images.withAlt / results.details.images.count) * 100);
addResultCard({
title: 'Images',
icon: 'fas fa-images',
status: imagesPercentage >= 90 ? 'good' : imagesPercentage >= 50 ? 'warning' : 'bad',
content: [
`<p>Total images: ${results.details.images.count}</p>
<p>Images with alt text: ${results.details.images.withAlt} (${imagesPercentage}%)</p>
<p class="${imagesPercentage >= 90 ? 'status-good' : imagesPercentage >= 50 ? 'status-warning' : 'status-bad'}">
${imagesPercentage >= 90 ? '✓ Good' : imagesPercentage >= 50 ? '⚠️ Could be better' : '✗ Needs improvement'}
</p>`,
`<span class="toggle-details">Show/hide details</span>
<div class="details-content">
Total Images: ${results.details.images.count}
\nImages with Alt Text: ${results.details.images.withAlt}
</div>`
].join('')
});
// Add links card
addResultCard({
title: 'Links',
icon: 'fas fa-link',
status: results.details.links.internal >= 5 ? 'good' : results.details.links.internal >= 2 ? 'warning' : 'bad',
content: [
`<p>Total links: ${results.details.links.count}</p>
<p>Internal links: ${results.details.links.internal}</p>
<p>External links: ${results.details.links.external}</p>
<p class="${results.details.links.internal >= 5 ? 'status-good' : results.details.links.internal >= 2 ? 'status-warning' : 'status-bad'}">
${results.details.links.internal >= 5 ? '✓ Good internal linking' :
results.details.links.internal >= 2 ? '⚠️ Could use more internal links' : '✗ Needs more internal links'}
</p>`,
`<span class="toggle-details">Show/hide details</span>
<div class="details-content">
Total Links: ${results.details.links.count}
\nInternal Links: ${results.details.links.internal}
\nExternal Links: ${results.details.links.external}
</div>`
].join('')
});
// Add content card
addResultCard({
title: 'Content',
icon: 'fas fa-align-left',
status: results.details.content.wordCount >= 500 ? 'good' : results.details.content.wordCount >= 300 ? 'warning' : 'bad',
content: [
`<p>Word count: ${results.details.content.wordCount}</p>
<p class="${results.details.content.wordCount >= 500 ? 'status-good' :
results.details.content.wordCount >= 300 ? 'status-warning' : 'status-bad'}">
${results.details.content.wordCount >= 500 ? '✓ Good length' :
results.details.content.wordCount >= 300 ? '⚠️ Could be longer' : '✗ Too short (consider expanding)'}
</p>`
].join('')
});
// Add keywords card only if keywords were provided
if (results.targetKeywords.length > 0) {
const keywordList = Object.entries(results.details.keywordDensity)
.map(([keyword, density]) =>
`<li>${keyword}: <strong>${density}%</strong> ${density >= 1 && density <= 2 ? '✓' : '⚠️'}</li>`
).join('');
addResultCard({
title: 'Keyword Density',
icon: 'fas fa-key',
status: 'good',
content: [
`<p>Target keywords analyzed:</p>
<ul class="keyword-density-list">${keywordList}</ul>
<p><small>Note: Ideal keyword density is typically 1-2% for each keyword.</small></p>`
].join('')
});
}
// Add recommendations card
const recommendations = [];
if (!results.details.title.exists) {
recommendations.push('<li><i class="fas fa-exclamation-circle issue-icon"></i> Add a title tag</li>');
} else if (results.details.title.status !== 'good') {
recommendations.push(`<li><i class="fas fa-exclamation-circle issue-icon"></i> Optimize title length (${results.details.title.status.replace('-', ' ')})</li>`);
}
if (!results.details.metaDescription.exists) {
recommendations.push('<li><i class="fas fa-exclamation-circle issue-icon"></i> Add a meta description</li>');
} else if (results.details.metaDescription.status !== 'good') {
recommendations.push(`<li><i class="fas fa-exclamation-circle issue-icon"></i> Optimize meta description length (${results.details.metaDescription.status.replace('-', ' ')})</li>`);
}
if (!results.details.headings.h1.exists) {
recommendations.push('<li><i class="fas fa-exclamation-circle issue-icon"></i> Add a H1 heading</li>');
}
if (results.details.headings.h2.count < 2) {
recommendations.push('<li><i class="fas fa-exclamation-circle issue-icon"></i> Consider adding more H2 headings</li>');
}
if (Math.round((results.details.images.withAlt / results.details.images.count) * 100) < 90) {
recommendations.push('<li><i class="fas fa-exclamation-circle issue-icon"></i> Add alt text to more images</li>');
}
if (results.details.links.internal < 5) {
recommendations.push('<li><i class="fas fa-exclamation-circle issue-icon"></i> Add more internal links</li>');
}
if (results.details.content.wordCount < 500) {
recommendations.push('<li><i class="fas fa-exclamation-circle issue-icon"></i> Consider expanding your content</li>');
}
if (results.targetKeywords.length > 0) {
Object.entries(results.details.keywordDensity).forEach(([keyword, density]) => {
if (density < 1 || density > 2) {
recommendations.push(`<li><i class="fas fa-exclamation-circle issue-icon"></i> Adjust keyword density for "${keyword}" (${density}%)</li>`);
}
});
}
if (recommendations.length === 0) {
recommendations.push('<li><i class="fas fa-check-circle" style="color: var(--success-color)"></i> No major issues detected!</li>');
}
addResultCard({
title: 'Recommendations',
icon: 'fas fa-lightbulb',
status: recommendations.length > 1 ? 'warning' : 'good',
width: 'full',
content: [
`<ul class="issues-list">${recommendations.join('')}</ul>`
].join('')
});
}
// Helper function to add a result card
function addResultCard(card) {
const cardElement = document.createElement('div');
cardElement.className = 'result-card';
if (card.width === 'full') {
cardElement.style.gridColumn = '1 / -1';
}
const statusText = card.status === 'good' ? 'Good' : card.status === 'warning' ? 'Needs Work' : 'Poor';
const statusClass = card.status === 'good' ? 'status-good' : card.status === 'warning' ? 'status-warning' : 'status-bad';
cardElement.innerHTML = `
<div class="card-header">
<h3 class="card-title">
<i class="${card.icon} card-icon"></i> ${card.title}
</h3>
<span class="card-status ${statusClass}">${statusText}</span>
</div>
<div class="result-details">
${card.content}
</div>
`;
resultsContent.appendChild(cardElement);
}
// Clear inputs function
function clearInputs() {
urlInput.value = '';
htmlInput.value = '';
keywordsInput.value = '';
resultsSection.style.display = 'none';
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
</html>