Validate your structured data implementation and check eligibility for rich search results
This tool helps you test and validate structured data on your website. It checks JSON-LD, Microdata, and RDFa to ensure your content is eligible for rich results in Google Search.
Rich results can include review stars, product prices, event dates, recipe information, and other enhanced features that improve click-through rates and visibility.
Enter a publicly accessible URL. The tool will fetch the page and analyze its structured data.
Paste your HTML code containing structured data. The tool will analyze JSON-LD, Microdata, and RDFa formats.
Try testing with these example data types:
Your structured data is valid and eligible for rich results. All required properties are present and correctly formatted.
The following schema types were detected in your structured data:
Article Schema:
├── @type: Article
├── headline: "Top 10 SEO Trends for 2025"
├── url: "https://www.1978.digital/blog/seo-trends"
├── datePublished: "2025-01-15"
└── author: { @type: "Person", name: "Alex Johnson" }
Organization Schema:
├── @type: Organization
├── name: "1978.Digital"
├── url: "https://www.1978.digital"
└── logo: "https://www.1978.digital/logo.png"
This is how your content might appear in Google Search results:
Google recommends JSON-LD for structured data. It's easier to implement and maintain than Microdata or RDFa. Place JSON-LD scripts in the <head> section of your HTML.
Always test your structured data before making it live, and re-test after implementation. Use this tool to validate syntax and check for eligibility issues.
Fill in as many required and recommended properties as possible. Complete data helps search engines better understand your content and increases chances of rich results.
Ensure all information in your structured data matches what's visible on the page. Update dates, prices, availability, and other time-sensitive information regularly.
Use Google Search Console to monitor how your rich results are performing. Track impressions, clicks, and any errors reported by Google.
If Google reports issues with your structured data, fix them as soon as possible. Persistent errors can prevent your content from appearing as rich results.
Pages can support multiple schema types. For example, an article page might include both Article and Organization schema. Use separate JSON-LD scripts for each type.
Content about SEO trends...
`, product: `Product description...
`, faq: `Structured data is code that helps search engines understand your content better.
JSON-LD is Google's preferred format because it's easy to implement and maintain.
Digital marketing agency...
` }; // Test results data const testResults = { status: 'pass', errors: 0, warnings: 1, totalIssues: 1, schemaTypes: ['Article', 'Organization'], issues: [ { type: 'info', title: 'JSON-LD Syntax Valid', message: 'Your JSON-LD structured data is syntactically correct and well-formed.', solution: '' }, { type: 'warning', title: 'Missing Image Property', message: 'The "image" property is recommended for better rich results appearance.', solution: 'Add an "image" property with a URL to a relevant image (minimum 1200x630px).' } ] }; // Initialize function initialize() { // Set today's date const today = new Date().toLocaleDateString(); // Set initial URL document.getElementById('testUrl').value = testData.url; // Add event listeners setupEventListeners(); } // Setup event listeners function setupEventListeners() { // Method toggle methodBtns.forEach(btn => { btn.addEventListener('click', function() { const method = this.getAttribute('data-method'); testData.method = method; // Update UI methodBtns.forEach(b => b.classList.remove('active')); this.classList.add('active'); inputSections.forEach(section => section.classList.remove('active')); document.getElementById(`${method}InputSection`).classList.add('active'); }); }); // Code type toggle codeTypeBtns.forEach(btn => { btn.addEventListener('click', function() { const type = this.getAttribute('data-type'); codeTypeBtns.forEach(b => b.classList.remove('active')); this.classList.add('active'); // Update code textarea placeholder based on type const textarea = document.getElementById('htmlCode'); const placeholders = { 'json-ld': 'Paste your JSON-LD structured data here...', 'microdata': 'Paste your HTML with Microdata here...', 'rdfa': 'Paste your HTML with RDFa here...', 'html': 'Paste your full HTML code here...' }; textarea.placeholder = placeholders[type] || 'Paste your code here...'; }); }); // Example buttons exampleBtns.forEach(btn => { btn.addEventListener('click', function() { const exampleType = this.getAttribute('data-example'); // Switch to code input method methodBtns.forEach(b => b.classList.remove('active')); document.querySelector('.method-btn[data-method="code"]').classList.add('active'); inputSections.forEach(section => section.classList.remove('active')); document.getElementById('codeInputSection').classList.add('active'); // Load example code document.getElementById('htmlCode').value = examples[exampleType] || ''; // Show success message const originalText = this.innerHTML; this.innerHTML = '✅ Loaded!'; setTimeout(() => { this.innerHTML = originalText; }, 2000); }); }); // Test button testBtn.addEventListener('click', runTest); // Fetch URL button fetchUrlBtn.addEventListener('click', runTest); // Reset button resetBtn.addEventListener('click', resetTest); // Test another button testAnotherBtn.addEventListener('click', function() { resultsSection.classList.remove('active'); // Scroll to top document.querySelector('.tester-section').scrollIntoView({ behavior: 'smooth' }); }); // Export report button exportReportBtn.addEventListener('click', exportReport); // Details tabs detailsTabs.forEach(tab => { tab.addEventListener('click', function() { const tabId = this.getAttribute('data-tab'); // Update tabs detailsTabs.forEach(t => t.classList.remove('active')); this.classList.add('active'); // Update contents detailsContents.forEach(content => content.classList.remove('active')); document.getElementById(`${tabId}Tab`).classList.add('active'); }); }); // Allow Enter key to trigger test document.getElementById('testUrl').addEventListener('keypress', function(e) { if (e.key === 'Enter') { runTest(); } }); } // Run test function runTest() { if (testData.method === 'url') { const url = document.getElementById('testUrl').value.trim(); if (!url) { alert('Please enter a URL to test'); return; } if (!url.startsWith('http://') && !url.startsWith('https://')) { alert('Please enter a valid URL starting with http:// or https://'); return; } testData.url = url; simulateUrlFetch(); } else { const code = document.getElementById('htmlCode').value.trim(); if (!code) { alert('Please enter HTML code to test'); return; } testData.code = code; analyzeCode(); } } // Simulate URL fetch (in real implementation, this would be an API call) function simulateUrlFetch() { // Show loading state const originalText = testBtn.innerHTML; testBtn.innerHTML = '⏳ Fetching & Analyzing...'; testBtn.disabled = true; // Simulate API delay setTimeout(() => { analyzeCode(); // For demo, we'll analyze example code testBtn.innerHTML = originalText; testBtn.disabled = false; }, 1500); } // Analyze code function analyzeCode() { // Determine which code to analyze let codeToAnalyze = testData.method === 'url' ? examples.article // Use example for URL method : testData.code; // Use user code for code method // Parse and analyze the code const analysis = analyzeStructuredData(codeToAnalyze); // Update UI with results updateResultsUI(analysis); // Show results section resultsSection.classList.add('active'); // Scroll to results resultsSection.scrollIntoView({ behavior: 'smooth' }); } // Analyze structured data function analyzeStructuredData(code) { // This is a simplified analysis for demonstration // In a real implementation, this would parse the code and validate against schema.org const analysis = { status: 'pass', errors: 0, warnings: 1, totalIssues: 1, schemaTypes: [], issues: [], detectedSchemas: [] }; // Check for JSON-LD if (code.includes('application/ld+json')) { analysis.schemaTypes.push('JSON-LD'); analysis.detectedSchemas.push({ type: 'JSON-LD', valid: true }); // Check for common schema types if (code.includes('"@type": "Article"') || code.includes('"@type":"Article"')) { analysis.schemaTypes.push('Article'); } if (code.includes('"@type": "Product"') || code.includes('"@type":"Product"')) { analysis.schemaTypes.push('Product'); } if (code.includes('"@type": "Organization"') || code.includes('"@type":"Organization"')) { analysis.schemaTypes.push('Organization'); } if (code.includes('"@type": "FAQPage"') || code.includes('"@type":"FAQPage"')) { analysis.schemaTypes.push('FAQPage'); } if (code.includes('"@type": "LocalBusiness"') || code.includes('"@type":"LocalBusiness"')) { analysis.schemaTypes.push('LocalBusiness'); } // Check for common issues if (!code.includes('"image"') && !code.includes('"ImageObject"')) { analysis.warnings++; analysis.totalIssues++; analysis.issues.push({ type: 'warning', title: 'Missing Image Property', message: 'The "image" property is recommended for better rich results appearance.', solution: 'Add an "image" property with a URL to a relevant image (minimum 1200x630px).' }); } // Check for required properties if (code.includes('"@type": "Article"') || code.includes('"@type":"Article"')) { if (!code.includes('"headline"') || !code.includes('"datePublished"')) { analysis.errors++; analysis.totalIssues++; analysis.issues.push({ type: 'error', title: 'Missing Required Article Properties', message: 'Article schema requires "headline" and "datePublished" properties.', solution: 'Add the missing required properties to your Article schema.' }); } } } else { analysis.warnings++; analysis.totalIssues++; analysis.issues.push({ type: 'warning', title: 'No JSON-LD Detected', message: 'No JSON-LD structured data was found. JSON-LD is Google\'s recommended format.', solution: 'Consider implementing JSON-LD structured data for better compatibility with Google Search.' }); } // Check for Microdata if (code.includes('itemscope') || code.includes('itemtype')) { analysis.schemaTypes.push('Microdata'); analysis.detectedSchemas.push({ type: 'Microdata', valid: true }); } // Check for RDFa if (code.includes('vocab=') || code.includes('typeof=') || code.includes('property=')) { analysis.schemaTypes.push('RDFa'); analysis.detectedSchemas.push({ type: 'RDFa', valid: true }); } // Update status based on errors if (analysis.errors > 0) { analysis.status = 'fail'; } else if (analysis.warnings > 0) { analysis.status = 'warning'; } else { analysis.status = 'pass'; } // Add success message if no issues if (analysis.totalIssues === 0) { analysis.issues.push({ type: 'info', title: 'No Issues Found', message: 'Your structured data appears to be valid and well-formed.', solution: '' }); } return analysis; } // Update results UI function updateResultsUI(analysis) { // Update status const statusElement = document.getElementById('validationStatus'); statusElement.textContent = analysis.status.toUpperCase(); statusElement.className = `summary-status status-${analysis.status}`; // Update counts document.getElementById('issuesCount').textContent = analysis.totalIssues; document.getElementById('errorCount').textContent = analysis.errors; document.getElementById('warningCount').textContent = analysis.warnings; document.getElementById('schemaCount').textContent = analysis.schemaTypes.length; // Update issue colors document.getElementById('issuesCount').className = `stat-value ${analysis.totalIssues === 0 ? 'pass' : analysis.errors > 0 ? 'error' : 'warning'}`; document.getElementById('errorCount').className = `stat-value ${analysis.errors === 0 ? 'pass' : 'error'}`; document.getElementById('warningCount').className = `stat-value ${analysis.warnings === 0 ? 'pass' : 'warning'}`; // Update issues list const issuesList = document.getElementById('issuesList'); const noIssuesMessage = document.getElementById('noIssuesMessage'); issuesList.innerHTML = ''; if (analysis.issues.length === 0) { noIssuesMessage.style.display = 'block'; } else { noIssuesMessage.style.display = 'none'; analysis.issues.forEach(issue => { const issueItem = document.createElement('li'); issueItem.className = `issue-item ${issue.type === 'error' ? 'warning' : issue.type}`; const typeClass = issue.type === 'error' ? 'type-error' : issue.type === 'warning' ? 'type-warning' : 'type-info'; issueItem.innerHTML = `