SEO GRAPHQL RANK MATH (ok)
Source Code
Step 1: Thử lấy seo với post
Bước 1: Tạo Dự Án Next.js mới
Chạy lệnh sau trong terminal để tạo một ứng dụng Next.js mới sử dụng TypeScript:
npx create-next-app@latest my-nextjs-app --typescript
Bước 3: Cài đặt Apollo Client và các thư viện cần thiết
Cài đặt Apollo Client, GraphQL và các thư viện cần thiết khác:
npm install @apollo/client graphql next-i18next
Bước 4: Thiết lập Apollo Client
Tạo một tệp apollo-client.ts
trong thư mục nguồn (ví dụ: src
hoặc ở cấp độ gốc tùy thuộc vào cách bạn tổ chức dự án):
pages\apollo-client.ts
// apollo-client.ts
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
const httpLink = createHttpLink({
uri: 'https://test1.com/graphql', // Địa chỉ GraphQL của WordPress
});
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache(),
});
export default client;
Bước 5: Cấu hình i18n
Tạo một tệp next-i18next.config.js
tại thư mục gốc của dự án:
next-i18next.config.js
// next-i18next.config.js
module.exports = {
i18n: {
locales: ['en', 'vi'],
defaultLocale: 'en',
},
};
Sau đó thêm vào next.config.js
để tích hợp i18n:
next.config.ts
const { i18n } = require('./next-i18next.config');
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
i18n,
reactStrictMode: true,
};
export default nextConfig;
Bước 6: Tạo Trang với SEO Metadata
Tạo tệp [...slug].tsx
trong thư mục pages
:
pages\[...slug].tsx
import { gql } from '@apollo/client';
import client from './apollo-client';
import { GetServerSideProps } from 'next';
import Head from 'next/head';
interface SeoMetadata {
title: string;
description: string;
focusKeywords: string;
}
interface PageProps {
seo: SeoMetadata;
}
const GET_SEO_METADATA = gql`
query GetSeoMetadata($slug: ID!) {
page(id: $slug, idType: URI) {
seo {
title
description
focusKeywords
}
}
}
`;
const Page: React.FC<PageProps> = ({ seo }) => {
return (
<div>
<Head>
<title>{seo.title}</title>
<meta name="description" content={seo.description} />
<meta name="keywords" content={seo.focusKeywords} />
</Head>
<p>Lorem ipsum dolor sit amet.</p>
</div>
);
};
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
const slugArray = Array.isArray(params?.slug) ? params.slug : [];
const slug = slugArray.join('/');
const { data } = await client.query({
query: GET_SEO_METADATA,
variables: { slug },
});
if (!data || !data.page) {
return {
notFound: true,
};
}
return {
props: {
seo: data.page.seo,
},
};
};
export default Page;
Bước 7: Khởi động Dự Án
Chạy ứng dụng Next.js bằng lệnh:
npm run dev




— Bổ sung tuyệt vời sử dụng hàm vừa lấy nội dung và lấy seo
pages\[...slug].tsx
import { gql } from '@apollo/client';
import client from './apollo-client';
import { GetServerSideProps } from 'next';
import Head from 'next/head';
interface SeoMetadata {
title: string;
description: string;
focusKeywords: string;
}
interface PageProps {
seo: SeoMetadata;
page: {
title: string;
content: string;
}
}
export const GET_SEO_METADATA = gql`
query GetSeoMetadata($slug: ID!) {
page(id: $slug, idType: URI) {
title
content
seo {
title
description
focusKeywords
}
}
}
`;
const Page: React.FC<PageProps> = ({ seo,page }) => {
console.log(page.content);
return (
<div>
<Head>
<title>{seo.title}</title>
<meta name="description" content={seo.description} />
<meta name="keywords" content={seo.focusKeywords} />
</Head>
<div dangerouslySetInnerHTML={{__html: page.content}}></div>
</div>
);
};
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
const slugArray = Array.isArray(params?.slug) ? params.slug : [];
const slug = slugArray.join('/');
const { data } = await client.query({
query: GET_SEO_METADATA,
variables: { slug },
});
if (!data || !data.page) {
return {
notFound: true,
};
}
return {
props: {
seo: data.page.seo,
page: data.page
},
};
};
export default Page;
— Cập nhật code cho blog sử dụng chung interface
pages\[...slug].tsx
import { gql } from '@apollo/client';
import client from './apollo-client';
import { GetServerSideProps } from 'next';
import Head from 'next/head';
export interface SeoMetadata {
title: string;
description: string;
focusKeywords: string;
}
export interface PageProps {
seo: SeoMetadata;
page: {
title: string;
content: string;
}
}
export const GET_SEO_METADATA = gql`
query GetSeoMetadata($slug: ID!) {
page(id: $slug, idType: URI) {
title
content
seo {
title
description
focusKeywords
}
}
}
`;
const Page: React.FC<PageProps> = ({ seo,page }) => {
console.log(page.content);
return (
<div>
<Head>
<title>{seo.title}</title>
<meta name="description" content={seo.description} />
<meta name="keywords" content={seo.focusKeywords} />
</Head>
<div dangerouslySetInnerHTML={{__html: page.content}}></div>
</div>
);
};
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
const slugArray = Array.isArray(params?.slug) ? params.slug : [];
const slug = slugArray.join('/');
const { data } = await client.query({
query: GET_SEO_METADATA,
variables: { slug },
});
if (!data || !data.page) {
return {
notFound: true,
};
}
return {
props: {
seo: data.page.seo,
page: data.page
},
};
};
export default Page;
Step 2 Thử lấy Seo với post




pages\posts\[slug].tsx
import { gql } from '@apollo/client';
import client from '../apollo-client'; // Đảm bảo đường dẫn chính xác
import { GetServerSideProps } from 'next';
import Head from 'next/head';
interface SeoMetadata {
title: string;
description: string;
focusKeywords: string;
}
interface Post {
seo: SeoMetadata;
title: string;
content: string;
}
interface PageProps {
post: Post | null; // Null nếu không tìm thấy
}
const GET_POST_METADATA = gql`
query GetPostMetadata($slug: ID!) {
post(id: $slug, idType: SLUG) {
title
content
seo {
title
description
focusKeywords
}
}
}
`;
const PostPage: React.FC<PageProps> = ({ post }) => {
if (!post) {
return <div>Không tìm thấy bài viết.</div>; // Hiển thị thông báo nếu bài viết không tồn tại
}
return (
<div>
<Head>
<title>{post.seo.title}</title>
<meta name="description" content={post.seo.description} />
<meta name="keywords" content={post.seo.focusKeywords} />
</Head>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</div>
);
};
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
const slug = params?.slug as string; // Đảm bảo rằng slug là string
const { data } = await client.query({
query: GET_POST_METADATA,
variables: { slug },
});
if (!data || !data.post) {
return {
notFound: true, // Trả về 404 nếu không tìm thấy bài viết
};
}
return {
props: {
post: data.post, // Truyền dữ liệu bài viết vào props
},
};
};
export default PostPage;
Step 3 Thử lấy Seo với category


pages\categories\[slug].tsx
import { gql } from '@apollo/client';
import client from '../apollo-client'; // Đảm bảo đường dẫn chính xác
import { GetServerSideProps } from 'next';
import Head from 'next/head';
interface SeoMetadata {
title: string;
description: string;
focusKeywords: string;
}
interface Post {
title: string;
slug: string;
}
interface Category {
name: string;
seo: SeoMetadata;
posts: {
nodes: Post[]; // danh sách bài viết
};
}
interface GeneralSettings {
title: string;
description: string;
}
interface CategoryMetadataResponse {
generalSettings: GeneralSettings;
category: Category;
}
interface PageProps {
category: Category | null; // Null nếu không tìm thấy
}
const GET_CATEGORY_METADATA = gql`
query GetCategoryMetadata($slug: ID!) {
category(id: $slug, idType: SLUG) {
name
seo {
title
description
focusKeywords
}
posts {
nodes {
title
slug
}
}
}
}
`;
const CategoryPage: React.FC<PageProps> = ({ category }) => {
if (!category) {
return <div>Không tìm thấy danh mục.</div>; // Hiển thị thông báo nếu danh mục không tồn tại
}
return (
<div>
<Head>
<title>{category.seo.title}</title>
<meta name="description" content={category.seo.description} />
<meta name="keywords" content={category.seo.focusKeywords} />
</Head>
<h1>{category.name}</h1>
<h2>Bài viết trong danh mục:</h2>
<ul>
{category.posts.nodes?.map(post => (
<li key={post.slug}>
<a href={`/posts/${post.slug}`}>{post.title}</a>
</li>
))}
</ul>
</div>
);
};
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
const slug = params?.slug as string; // Đảm bảo rằng slug là string
const { data } = await client.query<CategoryMetadataResponse>({
query: GET_CATEGORY_METADATA,
variables: { slug },
});
if (!data || !data.category) {
return {
notFound: true, // Trả về 404 nếu không tìm thấy danh mục
};
}
return {
props: {
category: data.category, // Truyền dữ liệu danh mục vào props
},
};
};
export default CategoryPage;
Step 4 Thử lấy Seo với Tag


pages\tags\[slug].tsx
import { gql } from '@apollo/client';
import client from '../apollo-client'; // Đảm bảo đường dẫn chính xác
import { GetServerSideProps } from 'next';
import Head from 'next/head';
interface SeoMetadata {
title: string;
description: string;
focusKeywords: string;
}
interface Post {
title: string;
slug: string;
}
interface Tag {
name: string;
seo: SeoMetadata;
posts: {
nodes: Post[]; // danh sách bài viết
};
}
interface GeneralSettings {
title: string;
description: string;
}
interface TagMetadataResponse {
generalSettings: GeneralSettings;
tag: Tag;
}
const GET_TAG_METADATA = gql`
query GetTagMetadata($slug: ID!) {
tag(id: $slug, idType: SLUG) {
name
seo {
title
description
focusKeywords
}
posts {
nodes {
title
slug
}
}
}
}
`;
const TagPage: React.FC<{ tag: Tag | null }> = ({ tag }) => {
if (!tag) {
return <div>Không tìm thấy thẻ.</div>; // Hiển thị thông báo nếu thẻ không tồn tại
}
return (
<div>
<Head>
<title>{tag.seo.title}</title>
<meta name="description" content={tag.seo.description} />
<meta name="keywords" content={tag.seo.focusKeywords} />
</Head>
<h1>{tag.name}</h1>
<h2>Bài viết trong thẻ:</h2>
<ul>
{tag.posts.nodes?.map(post => (
<li key={post.slug}>
<a href={`/posts/${post.slug}`}>{post.title}</a>
</li>
))}
</ul>
</div>
);
};
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
const slug = params?.slug as string; // Đảm bảo rằng slug là string
const { data } = await client.query<TagMetadataResponse>({
query: GET_TAG_METADATA,
variables: { slug },
});
if (!data || !data.tag) {
return {
notFound: true, // Trả về 404 nếu không tìm thấy thẻ
};
}
return {
props: {
tag: data.tag, // Truyền dữ liệu thẻ vào props
},
};
};
export default TagPage;
Step 5.1 Thử lấy Seo với blog



pages\blog\index.tsx
import { gql } from '@apollo/client';
import client from '../apollo-client'; // Đảm bảo đường dẫn chính xác
import Head from 'next/head';
interface SeoMetadata {
title: string;
description: string;
}
interface Post {
title: string;
slug: string;
}
interface BlogPostsResponse {
posts: {
nodes: Post[];
};
}
const GET_BLOG_POSTS = gql`
query GetBlogPosts {
posts {
nodes {
title
slug
}
}
}
`;
const BlogPage: React.FC<{ posts: Post[] }> = ({ posts }) => {
return (
<div>
<Head>
<title>Blog của tôi</title>
<meta name="description" content="Chào mừng bạn đến với blog của tôi." />
</Head>
<h1>Danh sách bài viết:</h1>
<ul>
{posts.map(post => (
<li key={post.slug}>
<a href={`/posts/${post.slug}`}>{post.title}</a>
</li>
))}
</ul>
</div>
);
};
export const getServerSideProps = async () => {
const { data } = await client.query<BlogPostsResponse>({
query: GET_BLOG_POSTS,
});
return {
props: {
posts: data.posts.nodes, // Truyền danh sách bài viết vào props
},
};
};
export default BlogPage;
Step 5.2 Thử lấy Seo với blog (Full)


import { gql } from '@apollo/client';
import client from '../apollo-client'; // Đảm bảo đường dẫn chính xác
import Head from 'next/head';
import { GET_SEO_METADATA } from '../[...slug]';
import { GetServerSideProps } from 'next';
interface SeoMetadata {
title: string;
description: string;
focusKeywords: string;
}
interface Post {
title: string;
slug: string;
}
interface BlogPostsResponse {
posts: {
nodes: Post[];
};
blog: SeoMetadata
}
const GET_BLOG_POSTS = gql`
query GetBlogPosts {
posts {
nodes {
title
slug
}
}
}
`;
const BlogPage: React.FC<{ posts: Post[],page: {seo: SeoMetadata} }> = ({ posts,page }) => {
return (
<div>
<Head>
<title>{page.seo.title}</title>
<meta name="description" content={page.seo.description} />
<meta name="keywords" content={page.seo.focusKeywords} />
</Head>
<h1>Danh sách bài viết:</h1>
<ul>
{posts.map(post => (
<li key={post.slug}>
<a href={`/posts/${post.slug}`}>{post.title}</a>
</li>
))}
</ul>
</div>
);
};
export const getServerSideProps: GetServerSideProps = async (context) => {
const { data } = await client.query<BlogPostsResponse>({
query: GET_BLOG_POSTS,
});
const lang = context.locale || context.params?.lang as string;
const slug = lang === 'en' ? 'blog-en' : `blog`;
const { data:blog } = await client.query({
query: GET_SEO_METADATA,
variables: { slug },
});
return {
props: {
posts: data.posts.nodes, // Truyền danh sách bài viết vào props
page:blog.page
},
};
};
export default BlogPage;
PreviousPlugin Unlimited Elements For Elementor nhakhoaemedic😍NextSEO GRAPHQL theo type page, post, product (ok)
Last updated
Was this helpful?