Skip to content

Latest commit

 

History

History
315 lines (240 loc) · 7.49 KB

File metadata and controls

315 lines (240 loc) · 7.49 KB

✅ SEO IMPLEMENTATION CHECKLIST

Quick Reference for Testing and Validation

🚀 Quick Start

  1. Start Dev Server

    npm run dev
  2. Open Validation Tool

    http://localhost:5173/seo-validator.html
    
  3. Test Different Pages

    • Change the path input (e.g., /topics/present-simple)
    • Click "Run SEO Validation"
    • Check all green ✓ marks

✅ Manual Validation Steps

Step 1: Check Homepage

URL: http://localhost:5173/

Open DevTools (F12) → Elements → <head>

Verify:

  • <title> contains "TypoGrammar"
  • <meta name="description"> exists (only ONE)
  • <link rel="canonical" href="https://typogrammar.com/"> (only ONE)
  • <meta property="og:title"> exists
  • <meta property="og:description"> exists
  • <meta property="og:url"> = "https://typogrammar.com/"
  • <meta property="og:image"> exists
  • <meta name="twitter:card"> = "summary_large_image"
  • At least 2 <script type="application/ld+json"> (WebSite + Organization)

Run in Console:

// Should all return 1
document.querySelectorAll('meta[name="description"]').length
document.querySelectorAll('link[rel="canonical"]').length
document.querySelectorAll('title').length

// Should return 2 or more
document.querySelectorAll('script[type="application/ld+json"]').length

Step 2: Check Grammar Topic Page

URL: http://localhost:5173/topics/present-simple

Verify:

Step 3: Check Page with usePageMetadata

URL: http://localhost:5173/ (HomePage uses usePageMetadata)

Verify:

  • Custom title from usePageMetadata is used (not overridden)
  • Custom description from usePageMetadata is used
  • OG tags reflect the custom values
  • No duplicate meta tags

🔍 Duplicate Check

Run in Console on ANY page:

// All should return 1 (not 2 or more)
console.log('Descriptions:', document.querySelectorAll('meta[name="description"]').length);
console.log('Canonicals:', document.querySelectorAll('link[rel="canonical"]').length);
console.log('Titles:', document.querySelectorAll('title').length);

// Should return 2+ (WebSite + Organization + optional others)
console.log('JSON-LD Scripts:', document.querySelectorAll('script[type="application/ld+json"]').length);

Expected Output:

Descriptions: 1
Canonicals: 1
Titles: 1
JSON-LD Scripts: 2 (or more)

🏗️ Build Validation

npm run build

Check:

  • No TypeScript errors
  • No build errors
  • dist/ folder created
  • File sizes acceptable (SEO adds ~5-10KB)

🌐 External Validation Tools

1. Facebook Sharing Debugger

URL: https://developers.facebook.com/tools/debug/

Steps:

  1. Enter: https://typogrammar.com/
  2. Click "Debug"
  3. Verify:
    • Title appears correctly
    • Description appears correctly
    • Image preview shows (if og:image set)

2. Twitter Card Validator

URL: https://cards-dev.twitter.com/validator

Steps:

  1. Enter: https://typogrammar.com/
  2. Click "Preview Card"
  3. Verify:
    • Card displays correctly
    • Title, description, image present

3. Google Rich Results Test

URL: https://search.google.com/test/rich-results

Steps:

  1. Enter: https://typogrammar.com/
  2. Wait for analysis
  3. Verify:
    • WebSite schema detected
    • Organization schema detected
    • No errors or warnings

4. Schema.org Validator

URL: https://validator.schema.org/

Steps:

  1. Copy JSON-LD from page source
  2. Paste into validator
  3. Verify:
    • No errors
    • All required fields present

📊 What to Look For

✅ GOOD (Should See)

<!-- Only ONE of each -->
<title>Present Simple | TypoGrammar</title>
<meta name="description" content="Learn Present Simple...">
<link rel="canonical" href="https://typogrammar.com/topics/present-simple">

<!-- Complete OG tags -->
<meta property="og:title" content="...">
<meta property="og:description" content="...">
<meta property="og:url" content="...">
<meta property="og:image" content="...">
<meta property="og:site_name" content="TypoGrammar">

<!-- Complete Twitter tags -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="...">
<meta name="twitter:description" content="...">
<meta name="twitter:image" content="...">

<!-- At least 2 JSON-LD scripts -->
<script type="application/ld+json" data-seo="true">
  {"@type": "WebSite", ...}
</script>
<script type="application/ld+json" data-seo="true">
  {"@type": "Organization", ...}
</script>

❌ BAD (Should NOT See)

<!-- Duplicates (BAD) -->
<title>...</title>
<title>...</title><meta name="description" content="...">
<meta name="description" content="..."><link rel="canonical" href="...">
<link rel="canonical" href="..."><!-- Missing tags (BAD) -->
<meta property="og:title">  <!-- No content attribute ❌ -->
<meta name="twitter:card" content="">  <!-- Empty content ❌ -->

<!-- Broken JSON-LD (BAD) -->
<script type="application/ld+json">
  {Invalid JSON}  
</script>

🔧 Troubleshooting

Issue: No SEO tags appear

Check:

  1. Is dev server running? (npm run dev)
  2. Is Layout.tsx rendering? (check browser DevTools)
  3. Are there errors in console? (F12 → Console)

Fix:

# Restart dev server
npm run dev

Issue: Duplicate meta tags

Check:

// Run in console
document.querySelectorAll('meta[name="description"]').length

If > 1:

  • Both global SEO and usePageMetadata are creating tags
  • This is expected behavior (usePageMetadata should take priority)
  • Verify the custom value is used, not the default

Issue: Title not updating on navigation

Check:

  • Does location.pathname change in React DevTools?
  • Is SEO component re-rendering?

Fix:

  • SEO component depends on props.path
  • Ensure Layout.tsx passes location.pathname

Issue: JSON-LD errors

Check:

// Run in console
Array.from(document.querySelectorAll('script[type="application/ld+json"]')).forEach(s => {
  try {
    JSON.parse(s.textContent);
    console.log('✓ Valid JSON');
  } catch (e) {
    console.error('✗ Invalid JSON:', e);
  }
});

Fix:

  • Check buildSeoMeta.ts for JSON structure
  • Ensure all strings are properly escaped

📈 Success Metrics

Before SEO Implementation

  • ❌ No canonical URLs
  • ❌ Missing OG tags
  • ❌ No Twitter cards
  • ❌ No structured data
  • ❌ Inconsistent titles
  • ❌ Manual meta tags per page

After SEO Implementation

  • ✅ Canonical URLs on ALL pages
  • ✅ Complete OG tags
  • ✅ Twitter cards configured
  • ✅ WebSite + Organization schemas
  • ✅ Auto-generated titles
  • ✅ Global system (one line in Layout.tsx)

🎯 Final Checklist

  • All 6 SEO files created in src/seo/
  • SEO component created in src/components/SEO.tsx
  • Layout.tsx updated with <SEO /> component
  • No TypeScript errors
  • Build succeeds (npm run build)
  • Homepage SEO validated
  • Topic page SEO validated
  • No duplicate meta tags
  • JSON-LD schemas present
  • Console has no errors
  • Backward compatible (usePageMetadata still works)

Status: Ready for Production ✅
Date: January 13, 2026
Next Step: Deploy to production and test live URLs with external validators