/**
* E-E-A-T Analyzer Plugin for LibreCrawl
* Analyzes Experience, Expertise, Authoritativeness, Trust signals on crawled pages
*
* @author LibreCrawl Community
* @version 1.0.0
*/
LibreCrawlPlugin.register({
// Plugin metadata
id: 'e-e-a-t',
name: 'E-E-A-T Analyzer',
version: '1.0.0',
author: 'LibreCrawl Community',
description: 'Analyzes Experience, Expertise, Authoritativeness, Trust (E-E-A-T) signals on your website',
// Tab configuration
tab: {
label: 'E-E-A-T',
icon: '🎓',
position: 'end' // Appears after all built-in tabs
},
// Plugin initialization
onLoad() {
console.log('📊 E-E-A-T Analyzer loaded');
},
// Called when tab becomes active
onTabActivate(container, data) {
console.log('🎓 E-E-A-T tab activated with', data.urls.length, 'URLs');
this.render(container, data);
},
// Called during live crawls when data updates
onDataUpdate(data) {
if (this.isActive && this.container) {
this.render(this.container, data);
}
},
// Called when crawl completes
onCrawlComplete(data) {
console.log('✅ E-E-A-T analysis complete for', data.urls.length, 'URLs');
if (this.isActive && this.container) {
this.render(this.container, data);
}
},
// Main render function
render(container, data) {
const { urls, links } = data;
if (!urls || urls.length === 0) {
container.innerHTML = this.renderEmptyState();
return;
}
// Analyze E-E-A-T signals
const analysis = this.analyzeEEAT(urls, links);
// Render the analysis
container.innerHTML = `
${this.renderHeader(analysis)}
${this.renderScoreCards(analysis)}
${this.renderSignalsBreakdown(analysis)}
${this.renderTopPages(analysis)}
${this.renderRecommendations(analysis)}
`;
},
// Render header section
renderHeader(analysis) {
return `
`;
},
// Render score cards
renderScoreCards(analysis) {
const scoreClass = this.getScoreClass(analysis.overallScore);
const scoreColor = this.getScoreColor(analysis.overallScore);
return `
Overall E-E-A-T Score
${analysis.overallScore}
Out of 100
Pages with Author Info
${analysis.pagesWithAuthor}
${this.getPercentage(analysis.pagesWithAuthor, analysis.totalPages)}% of pages
Pages with Schema Markup
${analysis.pagesWithSchema}
${this.getPercentage(analysis.pagesWithSchema, analysis.totalPages)}% of pages
External Citations
${analysis.externalCitations}
Average ${analysis.avgExternalLinks.toFixed(1)} per page
`;
},
// Render signals breakdown
renderSignalsBreakdown(analysis) {
return `
Trust Signals Breakdown
${this.renderSignalItem('✍️', 'Author Attribution', analysis.pagesWithAuthor, analysis.totalPages)}
${this.renderSignalItem('📊', 'Structured Data', analysis.pagesWithSchema, analysis.totalPages)}
${this.renderSignalItem('🔗', 'External Links', analysis.pagesWithExternalLinks, analysis.totalPages)}
${this.renderSignalItem('🏷️', 'Open Graph Tags', analysis.pagesWithOGTags, analysis.totalPages)}
${this.renderSignalItem('🔒', 'HTTPS Secure', analysis.securePages, analysis.totalPages)}
${this.renderSignalItem('📝', 'Sufficient Content', analysis.pagesWithGoodContent, analysis.totalPages)}
`;
},
// Render individual signal item
renderSignalItem(icon, label, count, total) {
const percentage = this.getPercentage(count, total);
const barColor = percentage >= 75 ? '#10b981' : percentage >= 50 ? '#f59e0b' : '#ef4444';
return `
${count}/${total}
${percentage}%
`;
},
// Render top pages by E-E-A-T score
renderTopPages(analysis) {
return `
Top Pages by E-E-A-T Score
| URL |
Score |
Author |
Schema |
Ext. Links |
${analysis.topPages.slice(0, 10).map(page => this.renderPageRow(page)).join('')}
`;
},
// Render individual page row
renderPageRow(page) {
const scoreColor = this.getScoreColor(page.score);
return `
|
${this.utils.escapeHtml(page.url)}
|
${page.score}
|
${page.hasAuthor ? '✅' : '❌'}
|
${page.hasSchema ? '✅' : '❌'}
|
${page.externalLinks}
|
`;
},
// Render recommendations
renderRecommendations(analysis) {
const recommendations = this.generateRecommendations(analysis);
return `
💡 Recommendations to Improve E-E-A-T
${recommendations.map(rec => this.renderRecommendation(rec)).join('')}
`;
},
// Render individual recommendation
renderRecommendation(rec) {
const priorityColors = {
high: '#ef4444',
medium: '#f59e0b',
low: '#3b82f6'
};
return `
${rec.icon}
${rec.title}
${rec.description}
${rec.priority}
`;
},
// Empty state
renderEmptyState() {
return `
🎓
No Data Yet
Start crawling to analyze E-E-A-T signals on your website
`;
},
// Analyze E-E-A-T signals across all URLs
analyzeEEAT(urls, links) {
let totalScore = 0;
let pagesWithAuthor = 0;
let pagesWithSchema = 0;
let pagesWithExternalLinks = 0;
let pagesWithOGTags = 0;
let securePages = 0;
let pagesWithGoodContent = 0;
let externalCitations = 0;
const pageScores = [];
urls.forEach(url => {
let score = 0;
const urlData = {
url: url.url,
score: 0,
hasAuthor: false,
hasSchema: false,
externalLinks: url.external_links || 0
};
// Check for HTTPS (10 points)
if (url.url && url.url.startsWith('https://')) {
score += 10;
securePages++;
}
// Check for author information (20 points)
if (url.meta_author || (url.og_tags && url.og_tags.author)) {
score += 20;
pagesWithAuthor++;
urlData.hasAuthor = true;
}
// Check for structured data/schema markup (25 points)
if (url.json_ld && url.json_ld.length > 0) {
score += 25;
pagesWithSchema++;
urlData.hasSchema = true;
}
// Check for external links/citations (15 points)
const extLinks = url.external_links || 0;
if (extLinks > 0) {
score += Math.min(15, extLinks * 3); // Up to 15 points
pagesWithExternalLinks++;
externalCitations += extLinks;
}
// Check for Open Graph tags (10 points)
if (url.og_tags && url.og_tags.title) {
score += 10;
pagesWithOGTags++;
}
// Check for sufficient content (20 points)
const wordCount = url.word_count || 0;
if (wordCount >= 300) {
score += 20;
pagesWithGoodContent++;
} else if (wordCount >= 150) {
score += 10;
}
urlData.score = Math.min(100, score);
totalScore += urlData.score;
pageScores.push(urlData);
});
// Sort pages by score
pageScores.sort((a, b) => b.score - a.score);
return {
totalPages: urls.length,
overallScore: urls.length > 0 ? Math.round(totalScore / urls.length) : 0,
pagesWithAuthor,
pagesWithSchema,
pagesWithExternalLinks,
pagesWithOGTags,
securePages,
pagesWithGoodContent,
externalCitations,
avgExternalLinks: urls.length > 0 ? externalCitations / urls.length : 0,
topPages: pageScores
};
},
// Generate recommendations based on analysis
generateRecommendations(analysis) {
const recommendations = [];
const total = analysis.totalPages;
// Author attribution
if (analysis.pagesWithAuthor < total * 0.5) {
recommendations.push({
icon: '✍️',
title: 'Add Author Information',
description: `Only ${analysis.pagesWithAuthor} out of ${total} pages have author information. Add author bylines with credentials to demonstrate expertise.`,
priority: 'high'
});
}
// Schema markup
if (analysis.pagesWithSchema < total * 0.3) {
recommendations.push({
icon: '📊',
title: 'Implement Structured Data',
description: `${analysis.pagesWithSchema} pages have schema markup. Add JSON-LD structured data (Article, Person, Organization schemas) to improve E-E-A-T.`,
priority: 'high'
});
}
// External citations
if (analysis.avgExternalLinks < 2) {
recommendations.push({
icon: '🔗',
title: 'Add External Citations',
description: `Average of ${analysis.avgExternalLinks.toFixed(1)} external links per page. Link to authoritative sources to support your claims and demonstrate research.`,
priority: 'medium'
});
}
// Content depth
if (analysis.pagesWithGoodContent < total * 0.7) {
recommendations.push({
icon: '📝',
title: 'Improve Content Depth',
description: `${analysis.pagesWithGoodContent} pages have sufficient content (300+ words). Create comprehensive, in-depth content to demonstrate expertise.`,
priority: 'medium'
});
}
// HTTPS
if (analysis.securePages < total) {
recommendations.push({
icon: '🔒',
title: 'Enable HTTPS Everywhere',
description: `${total - analysis.securePages} pages are not using HTTPS. Ensure all pages use HTTPS for trust and security.`,
priority: 'high'
});
}
// If no recommendations, add a positive message
if (recommendations.length === 0) {
recommendations.push({
icon: '🎉',
title: 'Great E-E-A-T Signals!',
description: 'Your website demonstrates strong Experience, Expertise, Authoritativeness, and Trust signals. Keep up the good work!',
priority: 'low'
});
}
return recommendations;
},
// Helper: Get score class
getScoreClass(score) {
if (score >= 80) return 'score-good';
if (score >= 60) return 'score-needs-improvement';
return 'score-poor';
},
// Helper: Get score color
getScoreColor(score) {
if (score >= 80) return '#10b981';
if (score >= 60) return '#f59e0b';
return '#ef4444';
},
// Helper: Get percentage
getPercentage(count, total) {
return total > 0 ? Math.round((count / total) * 100) : 0;
}
});
console.log('✅ E-E-A-T Analyzer plugin registered');