---
title: "Leveraging Azure AI and LangChain with Next.js to Boost SEO Performance"
description: "How to combine Azure OpenAI, LangChain, and Next.js `generateMetadata` to automatically generate SEO titles, descriptions, and keywords for e-commerce product pages, and cache them in Redis to save on AI usage."
canonical_url: "https://blog.markkulab.net/en/post/generate-seo-metadata-by-azure-ai"
author: "Mark Ku"
author_url: "https://blog.markkulab.net/en/author/mark-ku"
site: "Mark Ku's Tech Notes"
date_published: "2024-06-03 01:01:35 +0800"
category: "AI"
tags: ["ai", "seo", "azure openai", "langchain", "nextjs", "metadata", "redis", "ecommerce"]
language: "en"
license: "CC BY 4.0"
license_url: "https://creativecommons.org/licenses/by/4.0/"
attribution: "when reusing or quoting, credit the author and link back to the original"
---

# Leveraging Azure AI and LangChain with Next.js to Boost SEO Performance

## 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
1.  Page Request Handling: First, create an API in Next.js that accepts a page description and the target language.
2.  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.
3.  Result Caching: Then, store the keywords based on the page slug for the next pre-render. This also helps reduce Azure AI usage.
4.  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://ｗｗｗ.xxxx.de/api/lang-chain/seo-schema?description={page description }&langCode={translate to lang code}
```

## Example
```
http://ｗｗｗ.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, 高性能遊戲電腦"}
```

---

## About this article and its author

Originally published on [Mark Ku's Tech Notes](https://blog.markkulab.net/en/post/generate-seo-metadata-by-azure-ai)

License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) — when reusing or quoting, credit the author and link back to the original

### About the author

**[Mark Ku](https://blog.markkulab.net/en/author/mark-ku)** — Software Solution Provider

- 10+ years senior software engineer, now an AI Builder
- Focused on large-platform architecture — North-American e-commerce, AI SaaS subscription billing
- Combining AI Agents and automation to build evolvable product foundations

### Free tools built by the author

All of these are free to use:

- [Free PDF Sign Tool](https://blog.markkulab.net/en/tools/pdf-sign): Online PDF sign tool — draw, type, or upload a signature, then drag, resize, and download. Everything runs in your browser; nothing is uploaded.
- [VS Code Refactory](https://blog.markkulab.net/en/tools/refactory): Refactory is a VS Code refactoring extension: 34 actions plus a 37-rule code-smell inspection layer with a Code Health dashboard, across 18 languages, backed by 534 tests. It learns your repo's conventions: where interfaces live, where DI is registered, whether 'use client' belongs. It ranks files by git churn × complexity so you know what to fix first, and hands any smell to the Claude Code already on your machine. Free to use, and your source never leaves your computer.
- [DB-Kit Database Manager](https://blog.markkulab.net/en/tools/db-kit): DB-Kit is a lightweight, cross-platform database manager built with Tauri + Rust + React. Manage MySQL, MariaDB, PostgreSQL, SQL Server, Oracle, SQLite, MongoDB, Redis, Kafka, Elasticsearch and RabbitMQ from one consistent interface: passwords encrypted in the OS keychain, SSH tunnels, full CRUD, a visual query builder, stacked multi-statement result sets, cross-connection data transfer and compare/sync, Excel / CSV import & export, visualized execution plans, ER diagrams, scheduled backups, SQL stress testing with p50–p99 latency percentiles, a 15-rule SQL review engine, Kafka message browsing with monitoring & alerts, a bilingual UI (Traditional Chinese / English), a built-in AI assistant (natural-language SQL, AI review and tuning advice) and the dbk CLI. Free and open source (MIT), with installers for Windows, macOS and Linux.
- [VS Code Super Mermaid](https://blog.markkulab.net/en/tools/super-mermaid): Super Mermaid is a VS Code extension for beautiful Mermaid diagrams out of the box: auto-colored live preview, mouse pan & zoom, high-res PNG / SVG export, 21 templates and multiple themes. Free and open source (MIT).
- [React Super Mermaid](https://blog.markkulab.net/en/tools/react-super-mermaid): react-super-mermaid is an open-source React component library: render beautiful Mermaid diagrams with a single <MermaidViewer>, with built-in colorful / sketch themes, pan & zoom, in-diagram search, and high-res SVG / PNG export. Lightweight, SSR-safe, fully typed. Free and open source (MIT).
- [Jira / Confluence Super Mermaid](https://blog.markkulab.net/en/tools/jira-super-mermaid): An Atlassian Forge app: write Mermaid syntax directly inside a Jira issue or a Confluence page and get flowcharts, sequence diagrams, state machines and Gantt charts. 11 diagram types, SVG / PNG export, light and dark themes, full CJK support. Runs on Atlassian: your diagrams live in your own site and the app calls no third-party service. Free, coming soon to the Atlassian Marketplace.
- [Mermaid Live Preview](https://blog.markkulab.net/en/tools/mermaid-preview): Write Mermaid in your browser, see it render instantly, and share the whole diagram as a single link. No sign-up, nothing uploaded to a server, and mermaid.live share links work as-is.
- [React Intl Phone Number](https://blog.markkulab.net/en/tools/react-intl-phone-number): react-intl-phone-number is an open-source React component: framework-agnostic and antd-free, with E.164 in/out, a searchable flag / country-code dropdown, configurable validation levels (strict / mobile-strict / loose), themeable CSS, and i18n — phone logic powered by google-libphonenumber. Lightweight and fully typed. Free and open source (MIT).
- [Uptime Kuma Cluster](https://blog.markkulab.net/en/tools/uptime-kuma-cluster): Turn single-node Uptime Kuma into a highly available cluster: OpenResty + Lua smart load balancing, shared MariaDB state, health checks and automatic failover, plus cluster-management REST APIs. One Docker Compose command to start. Free and open source (MIT).
- [Special Education](https://blog.markkulab.net/en/education): Learning materials crafted for special education students

### Daily podcasts

- [Mark's Tech Insights — Daily AI News](https://blog.markkulab.net/en/category/tech-news): Daily curated AI and tech trends. Catch the latest developments via audio summaries — covering AI applications, software architecture, DevOps, and engineering practice. — RSS: https://blog.markkulab.net/feed.xml
- [AI股市蝦聊](https://blog.markkulab.net/en/category/ai-stock-chat): Every trading day, an AI-analyzed take on the Taiwan stock market, delivered as a two-host conversation covering the session and the next-day outlook. — RSS: https://blog.markkulab.net/ai-stock-chat/feed.xml
- [開源好物週報](https://blog.markkulab.net/en/category/open-source-weekly): A weekly two-host pick of free open-source tools surfaced from real Hacker News, GitHub, and Reddit buzz — what pain they solve and the fastest way to get started. — RSS: https://blog.markkulab.net/open-source-weekly/feed.xml

### Newsletter

[Subscribe to the newsletter](https://blog.markkulab.net/en/subscribe) — Be the first to know about new posts. No spam, unsubscribe anytime.
