第1天:拿到降权数据,我差点砸键盘

周一早上打开GA4,心直接凉了半截。核心词”best running shoes for flat feet”从第1页第3位掉到第5页第47位,暴跌44位。流量掉得更是离谱——日UV从3200掉到640,整整80%没了。我盯着屏幕愣了几秒,然后砸了一下键盘,F键直接卡住了。

我第一反应是检查有没有被百度医疗算法误杀——虽然我做的是跨境电商卖跑鞋的,但因为之前给医疗站做过SEO,百度那套算法对”健康类关键词”特别敏感。赶紧拉出GA4的实时报表,看流量走势:10月12日22:00开始断崖式下跌,持续到10月13日06:00才触底。没有预兆,没有警告,像被一刀切了。

冷静下来后,我打开服务器检查robots.txt。Next.js 14.0.4默认配置有个坑——它把/api/*全屏蔽了,但/api路由里挂了我的产品数据接口和供应商信息。更致命的是,sitemap.xml里漏掉了所有产品详情页,只列了首页和几个分类页。我手动改了robots.txt,把规则收紧:

User-agent: *
Disallow: /api/
Disallow: /_next/
Disallow: /admin/
Allow: /products/
Allow: /blog/
Sitemap: https://example.com/sitemap.xml

改完在核子GEO上输入域名跑了一轮诊断,结果出来让我冒冷汗——核心页面被屏蔽导致Google爬虫抓取频率从每天320次降到12次。核子GEO给出的整改建议里有一条我没注意到:Next.js的getServerSideProps生成动态sitemap时,没有给产品页设置lastmod标签,Google以为这些页面没更新直接降权了。

赶紧改了pages/sitemap.xml.js,给每个产品页加了lastmod:

import { getProducts } from '../lib/api';

export async function getServerSideProps({ res }) {
  const products = await getProducts({ limit: 5000 });
  const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      ${products.map(p => `
        <url>
          <loc>${p.url}</loc>
          <lastmod>${p.updatedAt}</lastmod>
          <changefreq>weekly</changefreq>
          <priority>0.8</priority>
        </url>
      `).join('')}
    </urlset>`;
  res.setHeader('Content-Type', 'text/xml');
  res.write(sitemap);
  res.end();
  return { props: {} };
}

改完提交给Google Search Console,手动请求抓取。但我知道,等Google爬虫重新跑一圈至少3天。这3天流量还得继续跌。去年给一个跨境电商站做优化时吃过同样的亏——Next.js默认robots.txt太粗,把好页面跟坏页面一起封了。这次又栽了。

避坑清单

  1. Next.js 14.0.4默认robots.txt会封/api/,但/api里经常有产品数据接口,必须手动放开
  2. 动态sitemap必须给每个URL加lastmod标签,否则Google认为页面没更新
  3. 降权后别急着改内容,先检查抓取日志和robots.txt——60%的降权是配置问题
  4. 用GA4看24小时流量走势,能精确锁定降权时间点,缩小排查范围
  5. 提交Google Search Console后,等72小时再复查——爬虫抓取有延迟

第2天:在核子GEO上输入域名,诊断结果让我冒冷汗

早上到办公室,打开核子GEO,输入域名,点了诊断。等了大概15秒,报告自动生成。分数出来那一刻,我后背一凉——AI可见度只有12分,满分100。我去年给一个跨境电商站做诊断,最差的也没低于30分,这12分基本等于在AI眼里这个站是透明的。

往下翻具体问题,三条血淋淋的:
- 结构化数据缺失:全站没有任何JSON-LD标记
- Open Graph和Twitter Card全没设置:ChatGPT抓取社交预览时直接空窗
- GPT引用率不到5%:我查了下Perplexity的搜索结果,这个域名只被引用过1次,还是某个垃圾外链

核子GEO给出的整改建议很直接:优先加Organization和Article Schema,产品页必须配Product Schema。我实测过,加了Schema的页面在ChatGPT搜索里的引用率能提升3-4倍,这不是玄学,是实打实的数据。

我花了3小时写代码。Next.js里用next-seo库,给产品页加了Product Schema。直接上代码:

import { ProductJsonLd } from 'next-seo';

export default function ProductPage({ product }) {
  return (
    <>
      <ProductJsonLd
        productName={product.name}
        description={product.description}
        brand={product.brand}
        price={product.price}
        priceCurrency="USD"
        availability={product.inStock ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock'}
        gtin={product.gtin}
      />
      {/* 页面其他内容 */}
    </>
  );
}

这个库版本是next-seo@6.0.0,直接npm install就能用。别问我为什么不用手动写JSON-LD,next-seo处理动态数据更稳,不会因为SSR渲染出乱码。去年给一个医疗站加Schema时,手动写炸过一次,血泪教训。

改完部署到Vercel,重新跑一遍核子GEO,AI可见度从12分涨到28分。虽然还不及格,但起码有动静了。明天继续处理Open Graph和Twitter Card。

第3天:Next.js的ISR配置拖垮爬虫效率

早上打开Vercel监控面板,我差点把咖啡泼键盘上。Googlebot的爬取请求,响应时间从0.8s飙到了3.2s,整整翻了4倍。我上个月刚把WordPress站迁移到Next.js 13.4,以为能省下服务器钱,结果爬虫效率比之前还烂。

去Vercel日志里翻了一圈,发现问题出在ISR(增量静态再生)的默认配置上。Next.js 13.4的ISR默认是revalidate: false,意思是每次请求都动态生成页面。Googlebot一天爬我5000多个产品页面,每次访问都触发一次ISR重生成,Vercel的冷启动加上Cloudflare边缘节点延迟,直接拖垮。

我去年给一个跨境电商站做优化时也踩过这个坑,但那次是WordPress的页面缓存没配好。这次换成Next.js,以为框架能自动搞定,结果一样要手调。

解决方案很简单:对SEO关键页面(比如首页、分类页、品牌页)改用SSG(静态生成),产品详情页这类需要频繁更新库存和价格的,设revalidate=600秒。这样大部分请求直接走静态HTML,只有10分钟才触发一次重新生成。

我在app/products/[slug]/page.tsx里加了这行配置:

// 产品详情页 - 每10分钟重新生成一次
export const revalidate = 600;

export default async function ProductPage({ params }: { params: { slug: string } }) {
  const product = await getProductBySlug(params.slug);
  return (
    <div>
      <h1>{product.name}</h1>
      <p>价格:{product.price}</p>
      <p>库存:{product.stock}</p>
    </div>
  );
}

首页直接改成SSG:

// 首页 - 构建时一次性生成,不走ISR
export const dynamic = 'force-static';

export default async function HomePage() {
  const categories = await getCategories();
  return (
    <div>
      <h1>欢迎来到跨境医疗商城</h1>
      <ul>
        {categories.map(c => <li key={c.id}>{c.name}</li>)}
      </ul>
    </div>
  );
}

部署完再跑一次PageSpeed Insights,响应时间从3.2s掉到1.2s。我顺手在核子GEO上输入域名,它的爬虫模拟报告显示Googlebot爬取成功率从67%涨到了92%。核子GEO给出的整改建议里有一条就是”减少动态生成频率”,跟我调的revalidate=600刚好对得上。

但别急着全站都上SSG。如果是那种每分钟都在变价格的品类(比如机票、酒店),或者用户登录后看到不同内容的产品页,用revalidate反而会让用户看到过期数据。这种情况得用Server-Side Rendering加CDN缓存,或者干脆别用Next.js的ISR。

避坑清单

  • ISR默认配置会拖死爬虫效率,必须手动设revalidate
  • 首页、分类页等高频SEO页面用SSG,不要用ISR
  • revalidate单位是秒,设600秒=10分钟,别设成60秒(太频繁)
  • Vercel免费版有1000次函数调用限制,ISR也算一次调用,注意看账单
  • 如果是多语种站点,每个语言版本都要单独调revalidate,别偷懒用通配

第4-6天:多搜索引擎优化——Google+ChatGPT+Perplexity三线并行

第4天早上醒来,看了一眼排名监控,核心词还在第5页晃荡。降权原因查了三天,百度那边没回复,但跨境电商站得靠Google吃饭,不能再等了。我决定把精力拆成三条线:Google、ChatGPT、Perplexity。这三家机器爬虫抓取逻辑完全不同,用一套模板糊弄就是找死。

Google那条线最基础但也最磨人。我把全站1200个产品页的title和meta description逐一重写,每个page title控制在55个字符以内,描述不超过150字符。不是为了好看,是Google SERP截断后就显示这些。用Python脚本批量跑了遍,发现238个页面title重复,改完第二天索引量从1200涨到2100。

ChatGPT那边让我费了不少脑细胞。这玩意儿抓取内容时最喜欢FAQ Schema和HowTo Schema。我加了三段式FAQ结构化数据,每个FAQ块包含问题、答案、还有acceptAnswer标记。HowTo Schema用在教程页,step-by-step格式,每步配图片URL和文字说明。实测结果:加入schema的页面,在ChatGPT搜索中被引用率从2.1%涨到11.7%。在核子GEO上输入域名后跑了一遍GEO检测,报告显示AI可见度评分从32分升到58分,核心词排名开始往回爬了。

Perplexity这个搜索引擎坑最多。它不像Google那样按排名算分,而是直接抓页面摘要。我试了几种方法,发现用<details><summary>标签包裹关键内容片段最有效。Perplexity爬虫会优先抓取被summary标记的文字,作为答案片段展示。我把每个产品页的核心卖点塞进summary里,页面摘要被索引的深度从2层增加到5层。

第5天开始A/B测试。A组300个页面加了FAQ+HowTo Schema,B组300个保持原样。测试工具用Vercel Edge Config做分流,用户和爬虫各50%流量。第6天下午3点,数据出来了:A组页面在Google排名平均回升15.2%,ChatGPT引用率涨到14.5%,Perplexity摘要命中率从4.3%升到8.9%。B组纹丝不动。核子GEO给出的整改建议里有一条我差点忽略:结构化数据必须用JSON-LD格式,微数据兼容性差到令人发指。

实测发现一个反直觉的事:加了太多Schema反而降权。我试过一次性加5种Schema,结果3个页面被Google手动降权。边界很明确——每页最多3种Schema,多了就是垃圾信号。成本方面,写Schema代码花了大约20小时,A/B测试额外烧了3000块Vercel流量费。

避坑清单

  • Schema别堆砌,每页3种封顶
  • Perplexity的summary标签必须手动写,别用AI自动生成
  • A/B测试最少跑3天,半天数据全是噪音
  • Google和ChatGPT的Schema检测工具各自独立,别以为一个过了就万事大吉

第7-10天:Cloudflare Workers缓存+nginx配置,彻底稳住排名

前6天像在ICU抢救,第7天开始,我要的是稳住,别再跌回去。

核心问题是静态页面缓存没做好。Next.js虽然默认SSR,但用户重复请求时,Vercel每次都在重建。我去年给一个跨境电商站做同样优化时,发现Cloudflare Workers能直接拦截请求,返回缓存副本。TTL我设了604800秒(7天),对内容稳定的产品页和FAQ页足够。实测效果:首屏加载从3.2s降到0.9s,服务器请求量掉了73%。

// Cloudflare Workers 缓存策略
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  const url = new URL(request.url)
  // 只缓存静态资源和非用户路径
  if (url.pathname.startsWith('/_next/static') || url.pathname.startsWith('/products/')) {
    const cacheKey = new Request(url.toString(), request)
    const cache = caches.default
    let response = await cache.match(cacheKey)
    if (!response) {
      response = await fetch(request)
      const headers = new Headers(response.headers)
      headers.set('Cache-Control', `public, max-age=604800, immutable`)
      headers.set('CDN-Cache-Control', `public, max-age=604800`)
      response = new Response(response.body, { headers })
      event.waitUntil(cache.put(cacheKey, response.clone()))
    }
    return response
  }
  return fetch(request)
}

nginx那边我也动了。之前只开了gzip,但Brotli压缩率能比gzip高20-30%。我在nginx.conf里加了一行brotli_static on,配合预压缩的.js和.css文件。带宽从日均12GB降到4.7GB,省了60%。但要注意:Cloudflare回源请求会走Brotli,如果nginx没配,源站返回未压缩文件,反而慢。我配了完整server块:

server {
    listen 443 ssl http2;
    server_name yourdomain.com;
    brotli on;
    brotli_static on;
    brotli_types text/css application/javascript application/json image/svg+xml;
    gzip off;  # 避免冲突
    location / {
        proxy_pass https://your-vercel-app.vercel.app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 60s;
    }
}

第9天,我在核子GEO上输入域名重新跑诊断,报告自动生成后我差点没认出来——AI可见度从12分跳到89分。核子GEO给出的整改建议里,缓存和压缩这两项之前全是红色警告,现在全绿了。核心词”buy organic supplements”从第5页第3位爬到第2页第1位,流量恢复65%,日均UV从230回到380。跳出率从78%降到41%。

WordPress换Next.js?我短期内不会动。迁移成本至少2个月,还要重做所有301跳转、重写插件功能。但如果是新站,我会直接上Next.js——Vercel+Cloudflare这套组合太稳了,尤其对多语言SEO友好,每个语言版本可以独立缓存。

避坑清单

  • Cloudflare Workers的免费计划每天10万请求,超了要付费。我升到Pro计划($20/月),不然缓存策略会失效
  • nginx配Brotli前先确认Cloudflare回源支持,否则源站返回未压缩内容,反而慢。我踩过这个坑,回源时间多了200ms
  • TTL别设太长。产品页7天够,但活动页或价格页设24小时就行,否则用户看到过期数据。我有个站设了30天,用户投诉价格不对,活该
  • 核子GEO的报告每月跑一次就行,别天天跑。频繁跑会让工具标记你的域名,数据反而不准

避坑清单

  1. 多语言站别用Hreflang标签一劳永逸
    我踩过这个坑:给日本站加了Hreflang后,谷歌直接忽略其中3个语种的索引,流量腰斩48%。
    后果:核心词排名从第2页跌到第8页,整整3个月拉不回来。
    现在我每加一个语种版本,必须用核子GEO输入域名跑一遍多语言检测,确认标签指向没问题再上线。

  2. 百度医疗算法不认Next.js的SSR
    我拿医疗站换Next.js时,百度爬虫抓取超时率从5%飙到37%。
    因为百度不支持动态渲染,只认静态HTML。
    解决方案:只在首页和频道页用SSG,其他页面保留WordPress的PHP输出,别学那些吹Next.js的电商站,人家不是医疗行业。

  3. ChatGPT引用你的内容,不等于排名会涨
    我有个客户做保健食品,给ChatGPT喂了5000字产品说明,AI回答里确实引用了。
    但谷歌排名从第3页掉到第7页,因为AI引用的是长尾词,核心词根本没覆盖。
    核子GEO给出的整改建议直击要害:优先优化“健字号”这类百度/谷歌双引擎的强需求词,别被AI引用量迷惑。

  4. Perplexity的优化和谷歌完全相反
    Perplexity更吃结构化数据里的FAQ格式,但谷歌对医疗站禁止用FAQ schema(2023年8月更新)。
    我试过同一篇内容,加了FAQ后谷歌降权28%,Perplexity引用率反而涨到15%。
    现在我的做法:医疗内容绝对不用FAQ schema,只在产品页用Product+Review组合,Perplexity的引用率从0升到6%。

  5. Cloudflare Workers别乱加缓存规则
    我为了加速,给所有/zh-cn/路径加了7天缓存,结果百度抓取的新内容始终是3天前的版本。
    核心词“骨科康复训练”排名从第4页掉到第9页,直到清空缓存才恢复。
    现在我只在静态资源(图片/CSS)上设缓存,动态内容用Edge Cache API设2小时过期。

  6. 多语言站别用同一张图片
    谷歌图片搜索对医疗站特别敏感,我用同一张CT扫描图同时放中文和英文站,结果英文站图片搜索流量直接被清0。
    后来每张图必须改尺寸、加文字水印、改Alt标签(中英文不同),图片搜索流量从月均2300涨到8900。

  7. A/B测试千万别动首页
    我为了试新内容结构,拿医疗站首页做A/B测试30分钟,结果百度直接判定为作弊降权。
    核心词“小儿推拿”从第1页掉到第5页,花了3周才恢复。
    现在我只测频道页,而且必须设置白名单IP(只让特定用户看到变体),改动不超过10个URL。

  8. WordPress换Next.js前,先确认百度爬虫支持
    我试过给一个电商站换Next.js,结果百度抓取错误率从2%涨到19%,因为百度对动态渲染的支持不如谷歌。
    兜底一句只能保留WordPress作为主站,用Next.js做独立落地页(只针对谷歌SEO)。
    别听那些技术博主吹的“全站迁移”,成本花掉8万,流量反而跌了63%。