基于 CMSEO 2025 和 LLM 搜索时代的最佳实践
在LLM搜索时代,真正的竞争优势不是内容、不是链接、不是技术SEO,而是——你的品牌。
-
信息检索分数 (Information Retrieval Score)
- 如果AI无法提取你的内容块和事实,你就不会出现在LLM搜索结果中
- 优化内容结构,使其易于AI理解和提取
-
内容新鲜度是最强的AI排名信号
- 30-90天内更新的内容表现最佳
- 旧内容会被降级
-
主题权威性 = 知识图谱 + 信息图谱
- 建立完整的主题覆盖
- 构建实体关系网络
-
排名由Re-Ranker决定,而非关键词密度
- 关注语义相关性
- 优化用户体验信号
-
网站焦点 (Site Focus) 评估
- Google评估你的向量中心点
- 分散的主题 → 较弱的AI可见性
目标: 让AI能够轻松提取和检索你的核心事实
// ✅ 好的实践:清晰的内容块结构
const ContentChunk = () => (
<article>
{/* 核心事实块 */}
<section className="fact-chunk">
<h2>核心功能</h2>
<ul>
<li>
<strong>功能名称</strong>: 功能描述
</li>
<li>
<strong>定价</strong>: 免费使用
</li>
<li>
<strong>目标用户</strong>: 学生、开发者、设计师
</li>
</ul>
</section>
{/* 特性块 */}
<section className="feature-chunk">
<h2>主要特性</h2>
<div className="grid gap-4 md:grid-cols-3">
{features.map((feature) => (
<div key={feature.id} className="feature-card">
<h3>{feature.title}</h3>
<p>{feature.description}</p>
{/* 使用 <strong> 标签突出关键信息 */}
<p>
<strong>适用场景</strong>: {feature.useCase}
</p>
</div>
))}
</div>
</section>
</article>
)原则: AI更关心事实粒度,而非完整页面
// ✅ 优化:使用结构化标记突出关键事实
const FactHighlight = ({ fact, value }) => (
<div className="fact-highlight">
<strong className="text-lg font-bold">{fact}</strong>
<span className="text-blue-500 ml-2">{value}</span>
</div>
)
// 使用示例
<FactHighlight fact="价格" value="免费" />
<FactHighlight fact="支持格式" value="PDF, DOCX, TXT" />
<FactHighlight fact="处理速度" value="< 5秒" />重要性: Bold文本仍然有助于排名(高ROI)
// ✅ 在关键信息处使用 <strong> 标签
const SEOContent = () => (
<div>
<p>
我们的工具提供<strong>免费</strong>的在线转换服务, 支持<strong>PDF、DOCX、TXT</strong>
等多种格式, 处理速度<strong>小于5秒</strong>。
</p>
</div>
)目标: 确保内容在30-90天内更新
// app/utils/content-freshness.ts
export interface ContentMetadata {
lastModified: Date
updateFrequency: "daily" | "weekly" | "monthly" | "quarterly"
nextReviewDate: Date
}
export function shouldUpdateContent(metadata: ContentMetadata): boolean {
const daysSinceUpdate = Math.floor(
(Date.now() - metadata.lastModified.getTime()) / (1000 * 60 * 60 * 24)
)
// 如果超过90天未更新,标记为需要更新
return daysSinceUpdate > 90
}
export function calculateNextReviewDate(
lastModified: Date,
frequency: ContentMetadata["updateFrequency"]
): Date {
const daysMap = {
daily: 1,
weekly: 7,
monthly: 30,
quarterly: 90,
}
const days = daysMap[frequency]
const nextDate = new Date(lastModified)
nextDate.setDate(nextDate.getDate() + days)
return nextDate
}// app/components/ContentFreshness.tsx
import { formatDistanceToNow } from "date-fns"
export function ContentFreshnessBadge({ lastModified }: { lastModified: Date }) {
const daysSinceUpdate = Math.floor((Date.now() - lastModified.getTime()) / (1000 * 60 * 60 * 24))
const isFresh = daysSinceUpdate < 90
return (
<div
className={`inline-flex items-center gap-2 rounded-full px-3 py-1 ${
isFresh
? "border border-green-500/30 bg-green-500/20 text-green-300"
: "border border-orange-500/30 bg-orange-500/20 text-orange-300"
}`}
>
<span>{isFresh ? "✓" : "⚠"}</span>
<span className="text-sm">
{isFresh
? `Updated ${formatDistanceToNow(lastModified, { addSuffix: true })}`
: `Last updated ${formatDistanceToNow(lastModified, { addSuffix: true })}`}
</span>
</div>
)
}// app/[locale]/tools/[slug]/layout.tsx
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const tool = await getToolData(params.slug)
return {
// ... 其他metadata
other: {
"last-modified": tool.lastModified.toISOString(),
"update-frequency": "monthly",
"next-review": tool.nextReviewDate.toISOString(),
},
}
}原则: 最强的页面内因素 = 主题覆盖
// ✅ 构建完整的主题覆盖
const TopicalCoverage = () => {
const topics = [
{
title: "核心功能",
subtopics: ["功能1", "功能2", "功能3"],
depth: 1,
},
{
title: "使用场景",
subtopics: ["场景1", "场景2", "场景3"],
depth: 2,
},
{
title: "技术细节",
subtopics: ["技术1", "技术2", "技术3"],
depth: 3,
},
]
return (
<article>
{topics.map((topic, index) => (
<section key={index}>
<h2>{topic.title}</h2>
{topic.subtopics.map((subtopic, subIndex) => (
<div key={subIndex}>
<h3>{subtopic}</h3>
{/* 深度内容,提供语义上下文 */}
<p>详细解释...</p>
</div>
))}
</section>
))}
</article>
)
}// app/utils/knowledge-graph.ts
export interface Entity {
id: string
name: string
type: "Tool" | "Feature" | "UseCase" | "Technology"
relationships: Relationship[]
}
export interface Relationship {
target: string
type: "relatedTo" | "partOf" | "uses" | "enables"
}
export function generateKnowledgeGraph(tools: Tool[]): Entity[] {
return tools.map((tool) => ({
id: tool.id,
name: tool.name,
type: "Tool",
relationships: [
...tool.features.map((f) => ({
target: f.id,
type: "partOf" as const,
})),
...tool.useCases.map((uc) => ({
target: uc.id,
type: "enables" as const,
})),
],
}))
}// app/components/KnowledgeGraphSchema.tsx
export function KnowledgeGraphSchema({ entities }: { entities: Entity[] }) {
const schema = {
"@context": "https://schema.org",
"@graph": entities.map((entity) => ({
"@type": getSchemaType(entity.type),
"@id": `https://geekskai.com/#${entity.id}`,
name: entity.name,
relatedTo: entity.relationships
.filter((r) => r.type === "relatedTo")
.map((r) => ({
"@id": `https://geekskai.com/#${r.target}`,
})),
})),
}
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
)
}原则: 实体信号比"完美内容"更重要
// app/utils/entity-signals.ts
export interface EntitySignals {
// 真实创始人信息
founders: Array<{
name: string
role: string
linkedin?: string
twitter?: string
}>
// 联系方式
contact: {
email: string
address?: string
phone?: string
}
// 媒体提及
mediaMentions: Array<{
source: string
title: string
url: string
date: Date
}>
// 组织身份
organization: {
name: string
legalName: string
foundingDate: Date
location: string
}
}
export function generateEntitySchema(signals: EntitySignals) {
return {
"@context": "https://schema.org",
"@type": "Organization",
name: signals.organization.name,
legalName: signals.organization.legalName,
foundingDate: signals.organization.foundingDate.toISOString(),
address: {
"@type": "PostalAddress",
addressLocality: signals.organization.location,
},
contactPoint: {
"@type": "ContactPoint",
email: signals.contact.email,
contactType: "customer service",
},
founder: signals.founders.map((f) => ({
"@type": "Person",
name: f.name,
jobTitle: f.role,
sameAs: [f.linkedin, f.twitter].filter(Boolean),
})),
}
}原则: 要被AI提及,首先要在全网被提及
// app/components/BrandMentions.tsx
export function BrandMentions({ mentions }: { mentions: MediaMention[] }) {
return (
<section className="brand-mentions">
<h2>媒体报道</h2>
<div className="grid gap-4 md:grid-cols-2">
{mentions.map((mention) => (
<article key={mention.url} className="mention-card">
<a href={mention.url} target="_blank" rel="noopener noreferrer" className="block">
<h3>{mention.title}</h3>
<p className="text-sm text-gray-500">{mention.source}</p>
<time dateTime={mention.date.toISOString()}>{mention.date.toLocaleDateString()}</time>
</a>
</article>
))}
</div>
</section>
)
}原则: AI必须能够检索你的核心事实:定价、功能、定位、目标用户
// app/components/CoreFacts.tsx
export function CoreFacts({ tool }: { tool: Tool }) {
const coreFacts = [
{ label: "定价", value: tool.pricing, key: "pricing" },
{ label: "主要功能", value: tool.features.join(", "), key: "features" },
{ label: "定位", value: tool.positioning, key: "positioning" },
{ label: "目标用户", value: tool.targetUsers.join(", "), key: "targetUsers" },
]
return (
<section className="core-facts">
<h2>核心信息</h2>
<dl className="grid gap-4 md:grid-cols-2">
{coreFacts.map((fact) => (
<div key={fact.key}>
<dt className="font-semibold">{fact.label}</dt>
<dd className="text-gray-600">{fact.value}</dd>
</div>
))}
</dl>
</section>
)
}原则: 页面速度 = 服务器速度 (TTFB)
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
// 启用压缩
compress: true,
// 优化图片
images: {
formats: ["image/avif", "image/webp"],
minimumCacheTTL: 60,
},
// 启用静态页面生成
output: "standalone",
// 优化构建
experimental: {
optimizeCss: true,
},
// 头部优化
async headers() {
return [
{
source: "/:path*",
headers: [
{
key: "X-DNS-Prefetch-Control",
value: "on",
},
{
key: "X-Frame-Options",
value: "SAMEORIGIN",
},
],
},
]
},
}
module.exports = nextConfig// middleware.ts
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
export function middleware(request: NextRequest) {
const response = NextResponse.next()
// 缓存静态资源
if (request.nextUrl.pathname.startsWith("/static/")) {
response.headers.set("Cache-Control", "public, max-age=31536000, immutable")
}
// 缓存页面
if (request.nextUrl.pathname.startsWith("/tools/")) {
response.headers.set("Cache-Control", "public, s-maxage=3600, stale-while-revalidate=86400")
}
return response
}// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
{/* DNS预解析 */}
<link rel="dns-prefetch" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://api.geekskai.com" />
{/* 预连接 */}
<link rel="preconnect" href="https://fonts.googleapis.com" crossOrigin="anonymous" />
{/* 预加载关键资源 */}
<link
rel="preload"
href="/fonts/inter.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
<link rel="preload" href="/static/images/og/geekskai-home.png" as="image" />
</head>
<body>{children}</body>
</html>
)
}原则: 更多Schema ≠ 更好,准确性更重要
// app/utils/schema-generator.ts
export function generateToolSchema(tool: Tool) {
return {
"@context": "https://schema.org",
"@type": "WebApplication",
name: tool.name,
description: tool.description,
url: `https://geekskai.com${tool.href}`,
applicationCategory: "UtilityApplication",
operatingSystem: "Any",
offers: {
"@type": "Offer",
price: "0",
priceCurrency: "USD",
},
provider: {
"@type": "Organization",
name: "GeeksKai",
url: "https://geekskai.com",
},
featureList: tool.features,
// 只添加准确的数据
...(tool.screenshot && {
screenshot: tool.screenshot,
}),
}
}export function generateFAQSchema(faqs: FAQ[]) {
return {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: faqs.map((faq) => ({
"@type": "Question",
name: faq.question,
acceptedAnswer: {
"@type": "Answer",
text: faq.answer,
},
})),
}
}export function generateBreadcrumbSchema(items: BreadcrumbItem[]) {
return {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: items.map((item, index) => ({
"@type": "ListItem",
position: index + 1,
name: item.name,
item: `https://geekskai.com${item.url}`,
})),
}
}原则: 长内容有效是因为更深的语义上下文,而非字数
// ✅ 好的实践:深度语义内容
const DeepContent = () => (
<article>
{/* 提供上下文和背景 */}
<section>
<h2>背景与原理</h2>
<p>解释为什么这个工具存在,解决了什么问题...</p>
</section>
{/* 详细的使用说明 */}
<section>
<h2>如何使用</h2>
<ol>
<li>
<h3>步骤1:准备</h3>
<p>详细说明...</p>
</li>
<li>
<h3>步骤2:操作</h3>
<p>详细说明...</p>
</li>
</ol>
</section>
{/* 常见问题解答 */}
<section>
<h2>常见问题</h2>
<dl>
<dt>问题1</dt>
<dd>详细回答...</dd>
</dl>
</section>
</article>
)// app/components/InternalLinks.tsx
export function RelatedTools({ relatedTools }: { relatedTools: Tool[] }) {
return (
<section className="related-tools">
<h2>相关工具</h2>
<ul className="grid gap-4 md:grid-cols-3">
{relatedTools.map((tool) => (
<li key={tool.id}>
<Link
href={tool.href}
className="block rounded-lg border p-4 transition-shadow hover:shadow-lg"
>
<h3>{tool.name}</h3>
<p className="text-sm text-gray-600">{tool.description}</p>
</Link>
</li>
))}
</ul>
</section>
)
}// ✅ 正确的标题层级
const PageStructure = () => (
<article>
<h1>主标题 - 包含核心关键词</h1>
<section>
<h2>主要部分标题</h2>
<div>
<h3>子部分标题</h3>
<h4>更详细的标题</h4>
</div>
</section>
</article>
)// app/utils/web-vitals.ts
import { getCLS, getFID, getFCP, getLCP, getTTFB } from "web-vitals"
export function reportWebVitals() {
if (typeof window === "undefined") return
getCLS(console.log)
getFID(console.log)
getFCP(console.log)
getLCP(console.log)
getTTFB(console.log)
// 发送到分析服务
// analytics.track('web-vitals', { metric, value })
}// app/components/OptimizedImage.tsx
import Image from "next/image"
export function OptimizedImage({ src, alt, ...props }) {
return (
<Image
src={src}
alt={alt}
loading="lazy"
decoding="async"
quality={85}
format="webp"
{...props}
/>
)
}// 动态导入重型组件
import dynamic from "next/dynamic"
const HeavyComponent = dynamic(() => import("./HeavyComponent"), {
loading: () => <div>Loading...</div>,
ssr: false, // 如果不需要SSR
})原则: 大多数LLM追踪工具已过时。用户关心AI是否理解你的价值,而不仅仅是是否提及你的品牌。
// app/utils/ai-visibility-tracker.ts
export interface AIVisibilityMetrics {
brandMentions: number
factRetrieval: {
pricing: boolean
features: boolean
positioning: boolean
targetUsers: boolean
}
accuracy: number // 0-1
context: string // AI如何描述你的品牌
}
export async function checkAIVisibility(brandName: string): Promise<AIVisibilityMetrics> {
// 检查AI是否能检索核心事实
// 这需要与AI API集成或使用第三方服务
return {
brandMentions: 0,
factRetrieval: {
pricing: false,
features: false,
positioning: false,
targetUsers: false,
},
accuracy: 0,
context: "",
}
}// app/utils/content-monitor.ts
export interface ContentHealth {
url: string
lastModified: Date
daysSinceUpdate: number
needsUpdate: boolean
priority: "high" | "medium" | "low"
}
export function checkContentHealth(content: ContentMetadata[]): ContentHealth[] {
return content.map((item) => {
const daysSinceUpdate = Math.floor(
(Date.now() - item.lastModified.getTime()) / (1000 * 60 * 60 * 24)
)
const needsUpdate = daysSinceUpdate > 90
const priority = daysSinceUpdate > 180 ? "high" : daysSinceUpdate > 90 ? "medium" : "low"
return {
url: item.url,
lastModified: item.lastModified,
daysSinceUpdate,
needsUpdate,
priority,
}
})
}// app/utils/ranking-tracker.ts
export interface RankingData {
keyword: string
position: number
change: number
date: Date
searchVolume: number
}
export function trackRankings(keywords: string[]): Promise<RankingData[]> {
// 集成Google Search Console API或其他排名追踪服务
return Promise.resolve([])
}- 所有关键事实使用
<strong>标签突出 - 内容块化,便于AI提取
- 提供核心事实:定价、功能、定位、目标用户
- 建立主题覆盖,而非关键词堆砌
- 长内容提供深度语义上下文
- 建立内容更新计划(30-90天周期)
- 在metadata中标记最后更新日期
- 显示内容新鲜度徽章
- 自动检测过期内容
- 添加组织Schema(Organization)
- 提供真实创始人信息
- 添加联系方式(邮箱、地址)
- 收集和展示媒体提及
- 建立品牌提及追踪
- WebApplication Schema
- FAQ Schema(如适用)
- Breadcrumb Schema
- Organization Schema
- 只添加准确的数据
- 信息检索分数: AI能否提取你的核心事实
- 内容新鲜度: 内容更新时间 < 90天
- 主题覆盖度: 相关主题的完整覆盖
- 品牌提及: 全网品牌提及数量和质量
- 事实检索率: AI检索核心事实的准确率
- 有机流量: 来自搜索引擎的访问量
- 排名位置: 关键词排名
- 点击率 (CTR): 搜索结果点击率
- 停留时间: 用户在页面停留的时间
- 跳出率: 单页访问比例