Introduction
As we know, AI excels at text processing. However, because our German website is a relatively small operation, we lack the manpower to maintain SEO data. To solve this, we're leveraging AI's text processing capabilities to automatically generate SEO data, including titles, descriptions, and keywords. This approach not only saves significant human resources but also improves the site's search engine optimization efficiency by sending data to the AI for processing during page pre-rendering.
The Revolution Brought by AI
Bill Gates once said that much of today's software is "still quite dumb" because it requires a lot of manual input to be useful. He believes that artificial intelligence (AI) agents can change this within the next five years.
From the past's mouse-and-keyboard input and acceptance of only explicit commands, we've moved to different interaction methods involving files, images, audio, and video, and the ability to understand ambiguous human instructions. The advent of AI has changed how humans interact with computers. And with this change in human-computer interaction, every application is worth rewriting with AI.
Technologies Used: Next.js, Azure Open AI, and LangChain
- Next.js: A React-based framework for building fast static and dynamic web applications. It allows developers to implement API routes directly within the framework, simplifying backend development.
- Azure Open AI: Everyone knows Microsoft invested in OpenAI. As a licensed partner, whenever a new model is released, Microsoft gets access to it simultaneously, packaging it to provide customized AI services for enterprises.
- LangChain: This is a framework for integrating multiple large AI models, making it easy to call various large language models. It provides templates, parsers, and dynamic routing, and can typically be integrated with other heterogeneous systems using FastAPI.
How Azure Open AI Works
The reason AI can understand context is that the entire conversation history is sent back with each request. This mechanism allows us to "wrap" the AI before making a request, assigning it a specific role and defining what it can and cannot do.
You are an SEO expert. Based on the page description provided below, generate an SEO-optimized title, meta description, and keywords. Ensure that the title is engaging and concise, the meta description summarizes the product effectively while enticing users to learn more, and the keywords are relevant to the product's features and market segment. Additionally, translate all content into the language specified by the given language code.
Company:{companyDescription}
Ecommerce Page Description: {description}
Translate Target Language Code: {langCode}
FormatInstructions: {formatInstructions}
Design Concept for the SEO Meta AI API
- Page Request Handling: First, create an API in Next.js that accepts a page description and the target language.
- Language Processing: Next, use LangChain to interact with Azure Chat OpenAI to generate SEO-optimized titles, descriptions, and keywords based on the provided page description.
- Result Caching: Then, store the keywords based on the page slug for the next pre-render. This also helps reduce Azure AI usage.
- Returning the Result: Finally, the generated SEO tag data is returned and used for the page's pre-rendering, aiming for better search engine rankings.
By combining Next.js's frontend technology, Azure AI's language generation capabilities, and LangChain's structured output, we can create an efficient and automated workflow to optimize our website's SEO performance. This method not only saves human resources but also improves the site's visibility and ranking in search engines due to its precise and targeted SEO tag generation.
Automated Generation of SEO-Compliant Tag Data
The generateSEOMetadata function deployed in Next.js utilizes Azure Chat OpenAI and LangChain to process product descriptions and generate corresponding titles, descriptions, and keywords. LangChain's Output Parser ensures that the response received from the AI model meets SEO requirements by extracting only the most critical information.
Next.js Code
import { BaseOutputParser } from '@langchain/core/output_parsers';
import { ChatPromptTemplate } from '@langchain/core/prompts';
import { AzureChatOpenAI } from '@langchain/openai';
import { LogLevel } from '@utils/log/const-logging';
import { serverSideLog } from '@utils/log/server-side-log';
import { genOnceEncodedURI } from '@utils/product/gear';
import { RedisBase } from '@utils/redis/redis-base';
import { NextApiRequest, NextApiResponse } from 'next';
class CustomOutputParser extends BaseOutputParser<string[]> {
async parse(output: any) {
const result = output.replaceAll('```json', '').replaceAll('```', ''); // for gpt4
const json = await JSON.parse(result);
return json;
}
getFormatInstructions() {
return 'Only the title, description and keywords of the json structure are returned. example :{"title":"","description":"","keywords":""} Please delete any other unnecessary information. Such as python code, Python Flask API, etc. Give me json result. Do not send back any other information such as python code, Python Flask API, etc.';
}
}
async function generateSEOMetadata(description: string, langCode: string) {
// https://{InstanceName}.openai.azure.com/openai/deployments/my-openai-deployment/
const model = new AzureChatOpenAI({
azureOpenAIApiKey: 'YOUR_AZURE_OPENAI_API_KEY',
azureOpenAIApiDeploymentName: 'YOUR_DEPLOYMENT_NAME', // gpt4
azureOpenAIApiInstanceName: 'YOUR_INSTANCE_NAME',
azureOpenAIApiVersion: '2024-02-01', // '2024-02-01',
temperature: 0, // 控制模型生成的隨機性或創造性
maxTokens: 500, // 指定模型生成的回應中最大可用的 token(詞的數量)
});
const prompt = ChatPromptTemplate.fromTemplate(
`
You are an SEO expert. Based on the page description provided below, generate an SEO-optimized title, meta description, and keywords. Ensure that the title is engaging and concise, the meta description summarizes the product effectively while enticing users to learn more, and the keywords are relevant to the product's features and market segment. Additionally, translate all content into the language specified by the given language code.
Company:{companyDescription}
Ecommerce Page Description: {description}
Translate Target Language Code: {langCode}
FormatInstructions: {formatInstructions}
`
);
const parser = new CustomOutputParser();
const companyDescription = `NXPower GmbH markets iBUYPOWER® Computer products in Germany, aiming to offer high-quality products at reasonable prices without compromising service.
We produce custom-made PC systems tailored to individual or business needs, ensuring the best possible system within your budget. Each PC is built with care, reflecting our passion and profession.
Every custom PC includes a 3-year pickup and return warranty, extensive testing, and a 24-hour burn-in test. Our sales team ensures you only pay for components you need, and our top IT technicians provide quick assistance for any issues.
We create dream computers to impress and delight you for years. Partnering with experienced and successful online retailers, we benefit from excellent support.
`;
const chain = prompt.pipe(model).pipe(parser);
const response = await chain.invoke({
companyDescription: companyDescription,
description: description,
langCode: langCode,
formatInstructions: parser.getFormatInstructions(),
});
return response;
}
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { description = '', slug = '', forceUpdate = false, langCode = 'en' } = req.query;
if (!description || !slug) {
return res.status(400).json({ error: 'Description must be a valid string.' });
}
const redis = new RedisBase();
const seoKey = 'SeoMata:' + langCode + ':' + genOnceEncodedURI(slug as string);
const seoResult = await redis.get(seoKey);
if (seoResult && !forceUpdate) {
return res.status(200).json(JSON.parse(seoResult));
}
// Process the description with Langchain and Azure AI
const metadata = await generateSEOMetadata(description as string, langCode as string);
await redis.setCacheKey(seoKey, JSON.stringify(metadata), -1);
// Save the metadata by slug to the database
// return data for pre-rendering
res.status(200).json(metadata);
} catch (err) {
serverSideLog('SEO Schema Error' + JSON.stringify(err), LogLevel.Error);
return res.status(500).json({ error: err });
}
}
In a Next.js 14 App Router, call the wrapped Azure AI API from the page's generateMetadata function.
export async function generateMetadata({ params }: Props): Promise<Metadata> {
// 構建URL
const pathname = new URL(headers().get('x-url')!).pathname;
const productData: IStoreModel | null = await getStoreModelData(params.locale, params.slug);
const description = generateTitleAndDescription(productData);
if (description === '') {
return generateDefaultMetadata(params.locale, params.slug);
}
const imageUrl = (productData && getAbsoluteImageUrl(productData.desc.info.image)) || '';
try {
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;
const queryParams = new URLSearchParams({
description: description,
langCode: params.locale,
slug: pathname,
// forceUpdate: 'true',
});
const url = `${baseUrl}/api/lang-chain/seo-schema?${queryParams.toString()}`;
// 獲取數據
const response = await fetch(url);
const seoMeta = await response.json();
const image: ImageProps = {
url: imageUrl,
width: 640,
height: 640,
alt: seoMeta.title,
};
// 返回Metadata
return {
title: seoMeta.title,
keywords: seoMeta.keywords,
description: seoMeta.description,
openGraph: {
title: seoMeta.title,
description: seoMeta.description,
...(imageUrl && {
images: image,
}),
},
twitter: {
title: seoMeta.title,
description: seoMeta.description,
card: 'summary_large_image',
},
};
} catch (e) {
return generateDefaultMetadata(params.locale, pathname);
}
}
And in the Middleware, get the slug and pass it in the header.
export default function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
request.headers.set('x-url', request.nextUrl.href);
return nextIntlMiddleware(request);
}
PS: The JavaScript version of LangChain isn't very stable. Much of the documentation is incorrect or describes fewer features compared to the Python version. It also tends to produce extra characters with different models, requiring a custom parser to handle. The ecosystem isn't as complete, so for complex scenarios, the Python version is recommended.
How to use
http://www.xxxx.de/api/lang-chain/seo-schema?description={page description }&langCode={translate to lang code}
Example
http://www.xxxx.de/api/lang-chain/seo-schema?description=Case:%20NZXT%20H5%20Flow%20Gaming%20Geh%C3%A4use%20-%20Schwarz%20Processor:%20AMD%20Ryzen%205%205600X%20Processor%20(6x%203.7GHz/32MB%20L3%20Cache)%20Memory:%2016GB%20DDR4/3200MHz%20Memory(G.Skill%20,Corsair,Kingston)%20Storage:%20Video%20Card:%20NVIDIA%20GeForce%20RTX%203050%20-%208GB%20GDDR6X%20(VR-Ready)%20Motherboard:%20ASRock%20B450%20PRO%204%20ATX%20USB%203.1,%20SATA3,%201x%20M.2&langCode=tw
Result
{"title":"頂級遊戲體驗:NZXT H5 Flow 黑色遊戲機殼配備 AMD Ryzen 5 與 RTX 3050","meta_description":"探索 NZXT H5 Flow 遊戲機殼,搭載 AMD Ryzen 5 5600X 處理器、16GB DDR4 記憶體、NVIDIA GeForce RTX 3050 顯示卡,為您的遊戲體驗帶來革命性提升。立即了解更多。","keywords":"NZXT H5 Flow, 遊戲機殼, AMD Ryzen 5 5600X, 16GB DDR4, NVIDIA GeForce RTX 3050, VR準備, ASRock B450 PRO 4, 高性能遊戲電腦"}





























Comments