SEO GRAPHQL theo type page, post, product (ok)
ưới đây là các truy vấn GraphQL đã viết sẵn để lấy metadata SEO từ Rank Math SEO cho từng loại: page
, post
, và product
(giả sử WooCommerce đang dùng WPGraphQL for WooCommerce).
✅ Truy vấn SEO cho Page
graphqlCopyEditquery GetPageSEOMetadata($uri: ID!) {
page(id: $uri, idType: URI) {
title
seo {
title
description
canonicalUrl
breadcrumbTitle
robots
focusKeywords
fullHead
jsonLd {
raw
}
breadcrumbs {
text
url
}
}
}
}
✅ Truy vấn SEO cho Post
graphqlCopyEditquery GetPostSEOMetadata($uri: ID!) {
post(id: $uri, idType: URI) {
title
seo {
title
description
canonicalUrl
breadcrumbTitle
robots
focusKeywords
fullHead
jsonLd {
raw
}
breadcrumbs {
text
url
}
}
}
}
✅ Truy vấn SEO cho Product (WooCommerce)
graphqlCopyEditquery GetProductSEOMetadata($uri: ID!) {
product(id: $uri, idType: URI) {
name
seo {
title
description
canonicalUrl
breadcrumbTitle
robots
focusKeywords
fullHead
jsonLd {
raw
}
breadcrumbs {
text
url
}
}
}
}
🔁 Tuỳ biến dùng chung (optionally)
Bạn cũng có thể viết 1 query "union" tùy biến nếu bạn dùng nodeByUri
(áp dụng nếu site bạn bật tính năng này):
graphqlCopyEditquery GetSEOMetadata($uri: String!) {
nodeByUri(uri: $uri) {
... on Page {
id
title
seo { ...SeoFields }
}
... on Post {
id
title
seo { ...SeoFields }
}
... on Product {
id
... on Node {
id
}
name
seo { ...SeoFields }
}
}
}
fragment SeoFields on SEO {
title
description
canonicalUrl
breadcrumbTitle
robots
focusKeywords
fullHead
jsonLd {
raw
}
breadcrumbs {
text
url
}
}
Nếu bạn đang dùng Next.js với Apollo Client, mình có thể giúp bạn viết sẵn hook
hoặc getStaticProps
/ getServerSideProps
để gọi mấy cái này cho chuẩn. Muốn không?
Tuyệt! Dưới đây là cách bạn có thể tích hợp lấy SEO metadata từ Rank Math SEO vào dự án Next.js sử dụng Apollo Client, với cả getStaticProps
, getServerSideProps
, và React hook
nếu dùng Client-side.
🔧 1. Cấu hình Apollo Client
Nếu bạn chưa có sẵn Apollo Client, bạn cần khởi tạo:
tsCopyEdit// lib/apollo-client.ts
import { ApolloClient, InMemoryCache } from '@apollo/client';
const client = new ApolloClient({
uri: 'https://your-wordpress-site.com/graphql', // thay bằng URL của bạn
cache: new InMemoryCache(),
});
export default client;
📦 2. Tạo GraphQL Query (dùng nodeByUri
)
nodeByUri
)tsCopyEdit// graphql/seo.ts
import { gql } from '@apollo/client';
export const GET_SEO_METADATA = gql`
query GetSEOMetadata($uri: String!) {
nodeByUri(uri: $uri) {
__typename
... on Page {
id
title
seo { ...SeoFields }
}
... on Post {
id
title
seo { ...SeoFields }
}
... on Product {
id
name
seo { ...SeoFields }
}
}
}
fragment SeoFields on SEO {
title
description
canonicalUrl
breadcrumbTitle
robots
focusKeywords
fullHead
jsonLd {
raw
}
breadcrumbs {
text
url
}
}
`;
🧠 3. getStaticProps
(Static Page với SEO)
getStaticProps
(Static Page với SEO)tsCopyEdit// pages/[slug].tsx
import { GetStaticProps } from 'next';
import client from '@/lib/apollo-client';
import { GET_SEO_METADATA } from '@/graphql/seo';
export const getStaticProps: GetStaticProps = async ({ params }) => {
const uri = `/${params?.slug || ''}`;
const { data } = await client.query({
query: GET_SEO_METADATA,
variables: { uri },
});
return {
props: {
seo: data?.nodeByUri?.seo ?? null,
},
revalidate: 60,
};
};
✅ Tương ứng với slug: /about
, /contact
, /products/abc
🕸 4. getServerSideProps
(SEO cập nhật real-time)
getServerSideProps
(SEO cập nhật real-time)tsCopyEditexport const getServerSideProps = async ({ params }) => {
const uri = `/${params.slug || ''}`;
const { data } = await client.query({
query: GET_SEO_METADATA,
variables: { uri },
});
return {
props: {
seo: data?.nodeByUri?.seo ?? null,
},
};
};
🪝 5. Custom Hook (Client-side fetching)
tsCopyEdit// hooks/useSEOMetadata.ts
import { useQuery } from '@apollo/client';
import { GET_SEO_METADATA } from '@/graphql/seo';
export function useSEOMetadata(uri: string) {
const { data, loading, error } = useQuery(GET_SEO_METADATA, {
variables: { uri },
});
return {
seo: data?.nodeByUri?.seo ?? null,
loading,
error,
};
}
🧠 6. Hiển thị SEO data trong <Head>
<Head>
tsxCopyEdit// components/SEO.tsx
import Head from 'next/head';
export default function SEO({ seo }) {
if (!seo) return null;
return (
<Head>
<title>{seo.title}</title>
<meta name="description" content={seo.description} />
<link rel="canonical" href={seo.canonicalUrl} />
{seo.robots && <meta name="robots" content={seo.robots} />}
{/* Inject full head HTML if you want */}
<div dangerouslySetInnerHTML={{ __html: seo.fullHead }} />
</Head>
);
}
Nếu bạn cho mình biết:
Bạn dùng App Router hay Pages Router?
Bạn có cần multi-language (i18n)?
Bạn dùng client-side hay server-side rendering?
Mình có thể tinh chỉnh đoạn code này phù hợp hơn 💡
Hoàn hảo! Vì bạn dùng:
Next.js Pages Router
i18n (đa ngôn ngữ) – ví dụ
/en/about
,/vi/about
Server-side Rendering (SSR)
Mình sẽ giúp bạn tối ưu toàn bộ flow lấy Rank Math SEO metadata theo đúng chuẩn, có thể xài cho bất kỳ trang nào (post
, page
, product
,...).
🧩 1. Cấu trúc URL hỗ trợ i18n
Trong Next.js pages
với i18n, bạn thường có:
tsCopyEdit// next.config.js
i18n: {
locales: ['en', 'vi'],
defaultLocale: 'en',
}
Nghĩa là:
/en/about
⇒ uri là/about
/vi/gioi-thieu
⇒ uri là/gioi-thieu
➡️ Ta cần tách locale
ra khỏi resolvedUrl
để lấy uri
.
🧠 2. Viết getServerSideProps
với i18n và Rank Math SEO
getServerSideProps
với i18n và Rank Math SEOtsxCopyEdit// pages/[...slug].tsx
import { GetServerSideProps } from 'next';
import client from '@/lib/apollo-client';
import { GET_SEO_METADATA } from '@/graphql/seo';
import SEO from '@/components/SEO';
export const getServerSideProps: GetServerSideProps = async ({ locale, resolvedUrl }) => {
// Remove locale prefix (e.g., "/vi/about" => "/about")
const uri = resolvedUrl.replace(/^\/[a-z]{2}(\/|$)/, '/');
const { data } = await client.query({
query: GET_SEO_METADATA,
variables: { uri },
});
return {
props: {
seo: data?.nodeByUri?.seo ?? null,
},
};
};
export default function Page({ seo }) {
return (
<>
<SEO seo={seo} />
<main>
{/* Nội dung trang ở đây */}
<h1>Hello Page</h1>
</main>
</>
);
}
🔁 3. File query GraphQL
tsCopyEdit// graphql/seo.ts
import { gql } from '@apollo/client';
export const GET_SEO_METADATA = gql`
query GetSEOMetadata($uri: String!) {
nodeByUri(uri: $uri) {
__typename
... on Page {
title
seo { ...SeoFields }
}
... on Post {
title
seo { ...SeoFields }
}
... on Product {
name
seo { ...SeoFields }
}
}
}
fragment SeoFields on SEO {
title
description
canonicalUrl
breadcrumbTitle
robots
focusKeywords
fullHead
jsonLd {
raw
}
breadcrumbs {
text
url
}
}
`;
🧱 4. Component SEO (inject vào <Head>
)
<Head>
)tsxCopyEdit// components/SEO.tsx
import Head from 'next/head';
export default function SEO({ seo }) {
if (!seo) return null;
return (
<Head>
<title>{seo.title}</title>
<meta name="description" content={seo.description || ''} />
<link rel="canonical" href={seo.canonicalUrl || ''} />
{seo.robots && <meta name="robots" content={seo.robots} />}
{seo.fullHead && (
<div dangerouslySetInnerHTML={{ __html: seo.fullHead }} />
)}
</Head>
);
}
✅ Kết quả:
Bạn có thể thêm SEO tự động cho mọi trang
/en/*
hoặc/vi/*
Sử dụng
SSR
để lấy đúng dữ liệu từ Rank Mathi18n xử lý chuẩn vì mình bóc
locale
khỏiresolvedUrl
Bạn có muốn mình giúp bạn xử lý luôn cả breadcrumbs hoặc tạo sitemap XML tự động từ Rank Math không?
Last updated
Was this helpful?