SEO for JavaScript Applications
JavaScript frameworks like React, Vue, and Angular create dynamic content that can be challenging for search engines to crawl. Understanding rendering strategies is key to JavaScript SEO.
Rendering Strategies
CSR - Client-Side Rendering
JavaScript renders content in the browser
SEO Challenge: Search engines may not see content
SSR - Server-Side Rendering
Server generates HTML for each request
SEO Benefit: Full content available immediately
SSG - Static Site Generation
HTML generated at build time
SEO Benefit: Fast, fully rendered pages
ISR - Incremental Static Regeneration
Static pages that update periodically
SEO Benefit: Fresh content with static performance
Next.js SEO Setup
// app/layout.tsx - Global metadata
import type { Metadata } from 'next';
export const metadata: Metadata = {
metadataBase: new URL('https://example.com'),
title: {
template: '%s | Site Name',
default: 'Site Name - Description',
},
description: 'Site description',
openGraph: {
type: 'website',
locale: 'en_US',
siteName: 'Site Name',
},
twitter: {
card: 'summary_large_image',
creator: '@handle',
},
robots: {
index: true,
follow: true,
},
};
// app/blog/[slug]/page.tsx - Dynamic metadata
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPost(params.slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: [post.image],
},
};
}
Static Generation for SEO
// Generate static paths at build time
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}
// Page component with data
export default async function BlogPost({ params }) {
const post = await getPost(params.slug);
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
// ISR - Revalidate every hour
export const revalidate = 3600;
Common JavaScript SEO Issues
Problems:
- Content loaded after initial render
- Links using onClick instead of href
- Infinite scroll without pagination
- Content behind user interactions
- Heavy JavaScript bundles
Solutions:
- Use SSR/SSG for critical content
- Use proper <a> tags with href
- Implement load more with URLs
- Server-render important content
- Code splitting and lazy loading
Testing JavaScript Rendering
// Test what Google sees
// 1. Google Search Console - URL Inspection
// Shows rendered HTML as Googlebot sees it
// 2. Chrome DevTools - Disable JavaScript
// Settings > Debugger > Disable JavaScript
// Check if critical content is visible
// 3. View source vs Inspect Element
// View source = what crawlers see initially
// Inspect = rendered DOM after JS
// 4. Fetch as Google / URL Inspection Tool
// Submit URLs to see crawled version