David Dumont
04/10/2022
Programmatic SEO is an excellent tool for transforming large amounts of data into web pages that respond perfectly to a user's specific search queries. With programmatic SEO, it is possible to focus on very specific keywords and significantly increase traffic to your site.
Imagine we want to answer the following query : "number of calories for an avocado"
, "apple calories"
or for hundreds of other fruits... Building a page and putting the data manually would be really time consuming by repeating the same page structure each time.
Fortunately, programmatic SEO can help us save a lot of time and Next.js give us very practical tools to generate hundred of static pages in few lines of code.
For simplicity, we have incorporated the fruits data into a data.ts file. In this file, we have and id, the name of the fruit, the calories for a standard amount served and the calories per 100 grams.
//data.js
export const fruitsData = [
{
"id": 1,
"name": "acai",
"serving": "1 oz. (28.35 g)",
"calories": "20 cal",
"calories_100g": "70 cal",
},
{
"id": 2,
"name": "apple",
"serving": "1 apple (182 g) ",
"calories": "95 cal",
"calories_100g": "52 cal",
},
{
"id": 3,
"name": "avocado",
"serving": "1 avocado (200 g)",
"calories": "320 cal",
"calories_100g": "160 cal",
},
{
"id": 4,
"name": "clementine",
"serving": "1 clementine (74 g)",
"calories": "35 cal",
"calories_100g": "47 cal",
},
{
"id": 5,
"name": "mango",
"serving": "1 mango (336 g)",
"calories": "202 cal",
"calories_100g": "60 cal",
},
{
"id": 6,
"name": "raisins",
"serving": "1 cup (145 g)",
"calories": "434 cal",
"calories_100g": "299 cal",
},
{
"id": 7,
"name": "rambutan",
"serving": "1 rambutan (9 g) ",
"calories": "7 cal",
"calories_100g": "82 cal",
},
{
"id": 8,
"name": "strawberries",
"serving": "1 cup (152 g)",
"calories": "434 cal",
"calories_100g": "32 cal",
},
{
"id": 9,
"name": "tangerine",
"serving": "1 tangerine (88 g)",
"calories": "47 cal",
"calories_100g": "53 cal",
},
{
"id": 10,
"name": "watermelon",
"serving": "1 wedge (286 g)",
"calories": "86 cal",
"calories_100g": "30 cal",
},
]
We now want to use the getStaticPaths and getStaticProps from Next.js (see their documentation : GetStaticPaths and GetStaticProps), that allows us to pre-render pages that use dynamic routes.
First, create a folder in the /pages folder. All pages generated will then be placed in the /fruit folder. The final url will be : /fruit/apple , /fruit/avocado, ...
We now have to create the component that will be rendering the content. This component is fed with data from the file including multiple fruit data.
During the build, the Next.js GetStaticPaths function will generate static pages according to the paths provided, and GetStaticProps will populate those pages with the correct data.
// pages/fruit/[index].js
import { fruitsData } from "../../data.js";
const FruitPage = ({ fruitData }) => {
return (
<div key={fruitData.id} className='mx-auto mt-8 text-center'>
<h1 className='text-4xl text-bold'>{fruitData.name} calories</h1>
<p>serving : {fruitData.serving}</p>
<p>calories : {fruitData.calories}</p>
<p>calories / 100g: {fruitData.calories_100g}</p>
</div>
);
};
export async function getStaticPaths() {
let paths = fruitsData.map((x) => {
return { params: { index: x.name } };
});
return {
paths,
fallback: false,
};
}
export async function getStaticProps(context) {
return {
props: { fruitData: fruitsData.find((e) => e.name == context.params.index) },
};
}
export default FruitPage;
During the build (npm run build), Next.js automatically generate static pages.
You can now access all pages via /fruit/... .
This method saves a lot of time when creating hundreds or thousands of pages from a database or an API.
It also allows to save time on the update of these pages, since it is enough to rebuild the pages with the updated data so that they are updated.
You can download the code on our github page :
10/4/2022
How to transform data into web pages with semi-programmatic SEO using Suncel CMS and Next.js ? Semi-programmatic SEO allows to add unique content on pages and add more unicity to the page.