SEO
See SEO for more general information.
Status Code
200
301/308
HTTP 301 Moved Permanently
Note: Next.js permanent redirects use 308 by default instead of 301 as it is the newer version and considered the better option.
// pages/about.js
export async function getStaticProps(context) {
return {
redirect: {
destination: '/',
permanent: true // triggers 308
}
}
}
or
// next.config.js
module.exports = {
async redirects() {
return [
{
source: '/about',
destination: '/',
permanent: true // triggers 308
}
]
}
}
302
HTTP 302 Found
The HyperText Transfer Protocol (HTTP) 302 Found
redirect status response code indicates that the resource requested has been temporarily moved to the URL given by the Location
header.
404
HTTP 404 Not Found
Resource not found.
export async function getStaticProps(context) {
return {
notFound: true // triggers 404
}
}
Custom 404 Page
// pages/404.js
export default function Custom404() {
return <h1>404 - Page Not Found</h1>
}
410
HTTP 410 Gone
Target resource is no longer available at the origin server and that this condition is likely to be permanent.
Used for content that are removed, e.g. threads deleted by user, blog post removed from site.
500
HTTP 500 Internal Server Error
Next.js will automatically return a 500
status code for an unexpected application error. You can create a custom 500
error page that is statically generated at build time by creating pages/500.js
.
// pages/500.js
export default function Custom500() {
return <h1>500 - Server-side error occurred</h1>
}
503
The HTTP 503 Service Unavailable
server error response code indicates that the server is not ready to handle the request.
Used when website is down and predicted that it will be down by an extended period of time. This prevents losing rankings on a long-term basis.
robots.txt
See robots.txt.
robots.txt
specifies which routes can be crawled and which are not.
In Next.js, add robots.txt
to public
folder.
// robots.txt
# Block all crawlers for /accounts
User-agent: *
Disallow: /accounts
# Allow all crawlers
User-agent: *
Allow: /
File available at http://<host>:<port>/robots.txt
.
Sitemaps
Read Sitemaps. ![[Sitemaps]]
Add sitemaps to Next.js
Manual
For a simple site, add public/sitemap.xml
<!-- public/sitemap.xml -->
<xml version="1.0" encoding="UTF-8">
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.example.com/foo</loc>
<lastmod>2021-06-01</lastmod>
</url>
</urlset>
</xml>
getServerSideProps
Generate dynamic sitemaps with getServerSideProps
.
Make file pages/sitemap.xml.js
.
// pages/sitemap.xml.js
const EXTERNAL_DATA_URL = 'https://jsonplaceholder.typicode.com/posts'
function generateSiteMap(posts) {
return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<!--We manually set the two URLs we know already-->
<url>
<loc>https://jsonplaceholder.typicode.com</loc>
</url>
<url>
<loc>https://jsonplaceholder.typicode.com/guide</loc>
</url>
${posts
.map(({ id }) => {
return `
<url>
<loc>${`${EXTERNAL_DATA_URL}/${id}`}</loc>
</url>
`
})
.join('')}
</urlset>
`
}
function SiteMap() {
// getServerSideProps will do the heavy lifting
}
export async function getServerSideProps({ res }) {
// We make an API call to gather the URLs for our site
const request = await fetch(EXTERNAL_DATA_URL)
const posts = await request.json()
// We generate the XML sitemap with the posts data
const sitemap = generateSiteMap(posts)
res.setHeader('Content-Type', 'text/xml')
// we send the XML to the browser
res.write(sitemap)
res.end()
return {
props: {}
}
}
export default SiteMap
Special Meta Tags for Search Engines
See Special Meta Tags for Search Engines. ![[MetaTag]]
Sample Code
import Head from 'next/head'
function IndexPage() {
return (
<div>
<Head>
<title>Meta Tag Example</title>
<meta name="google" content="nositelinkssearchbox" key="sitelinks" />
<meta name="google" content="notranslate" key="notranslate" />
</Head>
<p>Here we show some meta tags off!</p>
</div>
)
}
export default IndexPage
Canonical Tag
See Canonical Tag. ![[CanonicalTag]]
Rendering Strategies
The most important thing for SEO is that page data and metadata is available on page load without JavaScript.
- SSG (Static Site Generation)
- SSR (Server-Side Rendering)
- ISR (Incremental Static Regeneration)
- When there is a large amount of pages taking too much time to generate at build time. Next.js allows you to create or update static pages after you have built your site.
- Incremental Static Regeneration enables developers and content editors to use static generation on a per-page basis, without needing to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages
- CSR (Client Side Rendering)
See Rendering Strategies and Nextjs Basics for more details.
AMP
Nextjs supports AMP.
Performance & Core Web Vitals
See SEO for details.
Auto Image Optimization
On-demand Optimization
Instead of optimizing images at build time, Next.js optimizes images on-demand as users request them. Unlike static site generators and static-only solutions, build times don't increase, whether shipping ten images or ten million images.
Lazy Loaded Images
Images are lazy loaded by default. Page speed won't be penalized for images housed outside of the viewport. Images only load when they come into view.
Avoids CLS
Images are always rendered to avoid Cumulative Layout Shift (CLS).
Sample Code
import Image from 'next/image'
return <Image src="" alt="" width={1920} height={1080}/>
Dynamic Imports
Tutorial 1 Tutorial 2 Goal: reduce the amount of JavaScript loaded during initial page load from third-party libraries.
import dynamic from 'next/dynamic'
import CodeSampleModal from '../components/CodeSampleModal'
// Dynamic Import
const CodeSampleModal = dynamic(() => import('../components/CodeSampleModal'), {
ssr: false
})
Optimizing Fonts
Tutorial Next.js has built-in Automatic Webfont Optimization. By default, Next.js will automatically inline font CSS at build time, eliminating an extra round trip to fetch font declarations. This results in improvements to First Contentful Paint (FCP) and Largest Contentful Paint (LCP).
// regular version
<link href="https://fonts.googleapis.com/css2?family=Inter" rel="stylesheet" />
// optimized fonts
<style data-href="https://fonts.googleapis.com/css2?family=Inter">
@font-face{font-family:'Inter';font-style:normal.....
</style>
Optimizing Third-Party Scripts
Tutorial Embedding third-party authored code can delay page content from rendering and affect user performance if it is loaded too early. Next.js provides a built-in Script component that optimizes loading for any third-party script, while giving developers the option to decide when to fetch and execute it.
import Head from 'next/head'
import Script from 'next/script'
function IndexPage() {
return (
<div>
<Head>
<script src="https://www.googletagmanager.com/gtag/js?id=123" />
<!-- Optimized -->
<Script
strategy="afterInteractive"
src="https://www.googletagmanager.com/gtag/js?id=123"
/>
</Head>
</div>
)
}
Monitoring your Core Web Vitals
Next.js Analytics
Next.js Analytics allows you to analyze and measure the performance of pages using Core Web Vitals.
Custom Reporting
It is also possible to use the built-in relayer Next.js Analytics uses and send the data to your own service or push them to Google Analytics.
Add the following to pages/_app.js
.
export function reportWebVitals(metric) {
console.log(metric)
}
Data Studio
https://nextjs.org/learn/seo/monitor/data-studio Use Chrome User Experience Report dataset.
Reference
- https://nextjs.org/learn/seo/crawling-and-indexing/status-codes
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
- https://nextjs.org/learn/seo/crawling-and-indexing/metatags
- https://nextjs.org/learn/seo/rendering-and-ranking/rendering-strategies
- https://nextjs.org/learn/seo/rendering-and-ranking/metadata
- https://nextjs.org/learn/seo/web-performance
- https://nextjs.org/learn/seo/improve/images