tva
← Insights

แก้ปัญหา SEO หลังย้ายเว็บจาก WordPress มา Astro: Redirect Chains, Sitemaps และการจัดการ GSC

หลังจากย้ายเว็บจาก WordPress มา Astro เว็บไซต์ของคุณจะ build เร็วขึ้น โหลดเร็วขึ้น และค่าโฮสต์ถูกลง แต่ถ้า URL ของบล็อกเปลี่ยนไประหว่างการย้าย เช่น จาก /post-slug/ เป็น /insights/post-slug คุณอาจมีปัญหา SEO ที่จะปรากฏให้เห็นหลายสัปดาห์ต่อมาเมื่อ Google crawl เว็บไซต์ซ้ำจนครบ

Google Search Console จะเริ่มส่งอีเมลแจ้งเรื่อง "Duplicate, Google chose different canonical than user" และ "Not found (404) validation failed" หน้าที่เคยทำผลงานได้ดีอาจสูญเสีย link equity ไปกับ redirect ที่ไม่จำเป็น และคุณอาจมี sitemap สองตัวแข่งกันอยู่โดยไม่รู้ตัว

คู่มือนี้ครอบคลุมวิธีค้นหาและแก้ไขปัญหาเหล่านี้ทั้งหมด เราเจอทุกปัญหาที่กล่าวถึงระหว่างการ cleanup SEO หลังย้ายเว็บ WordPress มา Astro และได้บันทึกวิธีแก้ไขไว้ที่นี่

สิ่งที่คุณต้องมี

  • SSH access เข้าเซิร์ฟเวอร์ (สำหรับตั้งค่า nginx)
  • สิทธิ์เข้าถึง Google Search Console สำหรับ property ของคุณ
  • curl ติดตั้งไว้ในเครื่อง
  • เครื่องมือ analytics (เราใช้ Plausible ที่โฮสต์เอง)

ปัญหาที่จะได้รับการแก้ไข

  • ลด redirect chain หลายขั้น (2 ขั้นขึ้นไป) เหลือ 301 ขั้นเดียว
  • รวม sitemap ที่แข่งกันให้เหลือแหล่งเดียวที่สร้างอัตโนมัติ
  • นำหน้าที่ติด noindex ออกจาก sitemap
  • ล้าง GSC property เก่าและ sitemap WordPress ที่ค้างอยู่
  • แก้ความสับสน canonical ระหว่างโครงสร้าง URL เก่าและใหม่

ขั้นตอนที่ 1: วินิจฉัย Redirect Chains

ตรวจสอบว่า URL หลักของคุณผ่าน redirect กี่ครั้ง ถ้า URL ของ WordPress มี trailing slash แต่ URL ของ Astro ไม่มี คุณน่าจะมี chain สองขั้น: redirect แรกตัด slash ออก แล้ว redirect ที่สองเพิ่ม path prefix ใหม่

curl -sL -w "Hops: %{num_redirects}, Final: %{http_code}, URL: %{url_effective}\n" \
  -o /dev/null "https://yourdomain.com/old-post-slug/"

ถ้าผลลัพธ์แสดง Hops: 2 แสดงว่าคุณมี redirect chain ให้รันคำสั่งนี้กับ 5 หน้าที่มีผู้เข้าชมสูงสุด เพราะนั่นคือหน้าที่การสูญเสีย link equity ส่งผลกระทบมากที่สุด

ตรวจสอบเพิ่มเติมด้วยข้อมูล analytics ถ้าคุณเห็นบทความเดียวกันปรากฏใน URL หลายรูปแบบ (มี slash, ไม่มี slash, มี prefix ใหม่) แสดงว่า redirect ไม่ได้รวม traffic ไว้ที่เดียว เราพบว่าบทความยอดนิยมของเราแตกกระจายออกเป็นสาม URL variant ใน Plausible ซึ่งยืนยันปัญหา chain ดังกล่าว

ขั้นตอนที่ 2: ตั้งค่า nginx ให้ Redirect ขั้นเดียว

rule ตัด trailing slash มาตรฐานของ nginx มีลักษณะดังนี้:

location ~ ^(.+)/$ { return 301 $1; }

rule นี้ตัด trailing slash ออก แต่ไม่รู้เรื่องการเปลี่ยน path ของบล็อก request จึงไปชน rule ที่สอง ซึ่ง redirect /slug ไปยัง /insights/slug รวมเป็นสองขั้น

แทนที่ด้วย rule ที่รู้จักบล็อก โดยตรวจสอบว่า slug ตรงกับบทความบล็อกหรือไม่ แล้ว redirect ตรงไปยัง URL ปลายทางเลย:

# Blog slugs with trailing slash — single-hop to /insights/
location ~ ^/([^/]+)/$ {
    set $slug $1;
    if (-f /usr/share/nginx/html/insights/$slug/index.html) {
        return 301 https://yourdomain.com/insights/$slug;
    }
    return 301 https://yourdomain.com/$slug;
}
# Multi-segment paths — just strip the slash
location ~ ^(.+)/$ { return 301 $1; }

rule แรกรับมือ slug ระดับ root (URL บล็อก WordPress เก่าของคุณ) โดยตรวจสอบว่ามีหน้าที่ตรงกันอยู่ใต้ /insights/ หรือไม่ แล้ว redirect ไปตรงๆ เลย path ที่ไม่ใช่บล็อกจะผ่านไปยัง rule ตัด slash ทั่วไป หลัง deploy แล้วให้ตรวจสอบ:

curl -sL -w "Hops: %{num_redirects}\n" -o /dev/null \
  "https://yourdomain.com/your-top-post-slug/"
# Expected: Hops: 1

ขั้นตอนที่ 3: รวม Sitemaps ให้เป็นหนึ่งเดียว

ตรวจสอบว่าคุณมี sitemap มากกว่าหนึ่งตัวหรือไม่ รูปแบบที่พบบ่อยหลังการย้าย: sitemap.xml แบบ static ที่สร้างเองระหว่างย้าย บวกกับ sitemap-index.xml ที่สร้างอัตโนมัติจาก integration @astrojs/sitemap ของ Astro

# Check both
curl -sI "https://yourdomain.com/sitemap.xml" | head -1
curl -sI "https://yourdomain.com/sitemap-index.xml" | head -1

ถ้าทั้งสองคืนค่า 200 แสดงว่าคุณมี sitemap แข่งกัน ตรวจสอบว่า robots.txt อ้างอิงอันไหน:

curl -s "https://yourdomain.com/robots.txt" | grep -i sitemap

วิธีแก้: ลบ sitemap.xml แบบ static ออกจากไดเรกทอรี public/ อัปเดต robots.txt ให้ชี้ไปที่ sitemap-index.xml และปล่อยให้ integration ของ Astro จัดการทุกอย่าง บทความใหม่จะปรากฏใน sitemap โดยอัตโนมัติทุกครั้งที่ build

ตรวจสอบ sitemap แบบ static ด้วยว่ามีหน้าที่ติด noindex อยู่หรือไม่ ถ้า sitemap.xml ของคุณแสดงหน้าอย่าง /legal หรือ /privacy-policy ที่มี <meta name="robots" content="noindex"> คุณกำลังส่งสัญญาณขัดแย้งให้ Google sitemap ที่สร้างอัตโนมัติจาก @astrojs/sitemap สามารถตั้งค่า filter rule เพื่อกรองหน้าเหล่านี้ออกได้อย่างถูกต้อง

ขั้นตอนที่ 4: จัดการ Google Search Console

เปิด GSC และตรวจสอบสองสิ่ง: properties และ sitemaps

Properties: ถ้าคุณมีทั้ง domain property (sc-domain:yourdomain.com) และ URL prefix property (https://www.yourdomain.com/) คุณจะได้รับแจ้งเตือนซ้ำสำหรับปัญหาเดิม เลือกอันใดอันหนึ่ง ถ้า subdomain ของคุณเป็นโปรเจกต์แยกต่างหาก URL prefix property จะสะอาดกว่า เพราะรายงานเฉพาะ traffic บน production เท่านั้น

Sitemaps: ไปที่ Indexing → Sitemaps ลบ sitemap WordPress เก่าที่ยังค้างอยู่ (post-sitemap.xml, page-sitemap.xml, sitemap-post-type-product.xml และอื่นๆ) จากนั้น submit sitemap-index.xml ใหม่เป็น sitemap เดียว

404 Validation: ไปที่ Indexing → Pages → "Not found (404)" และดูว่ามี URL อะไรบ้าง ถ้าเป็น path WordPress เก่าที่ไม่มีอยู่แล้วและไม่ควรมี (หน้าสินค้า WooCommerce, หน้า author, feed URL) Google จะ deindex เองตามเวลา แต่ถ้าเป็นบทความบล็อกที่ควรมี redirect rule ใน nginx ของคุณต้องอัปเดต หลังแก้ redirect แล้ว ให้กด "Validate Fix" เพื่อสั่ง re-crawl

ขั้นตอนที่ 5: ตรวจสอบทุกอย่าง

รันการตรวจสอบเหล่านี้หลัง deploy การแก้ไขทั้งหมด:

# 1. Redirect chains resolved
curl -sL -w "Hops: %{num_redirects}, URL: %{url_effective}\n" \
  -o /dev/null "https://yourdomain.com/your-top-post/"
# Expected: Hops: 1, URL ends in /insights/your-top-post

# 2. robots.txt points to generated sitemap
curl -s "https://yourdomain.com/robots.txt" | grep sitemap
# Expected: sitemap-index.xml

# 3. Old static sitemap returns 404
curl -sI "https://yourdomain.com/sitemap.xml" | head -1
# Expected: 404

# 4. Generated sitemap returns 200
curl -sI "https://yourdomain.com/sitemap-index.xml" | head -1
# Expected: 200

# 5. Non-www redirects to www
curl -sI -o /dev/null -w "%{http_code} %{redirect_url}\n" \
  "https://yourdomain.com/insights"
# Expected: 301 https://www.yourdomain.com/insights

Google ต้องใช้เวลานานแค่ไหนในการอัปเดต

single-hop redirect มีผลทันทีสำหรับการ crawl ครั้งถัดไป การเปลี่ยน sitemap ใช้เวลาไม่กี่วันกว่า Google จะรับรู้ ส่วนความสับสน canonical ที่ Google ยังเลือก URL เก่าแทน URL ใหม่นั้นต้องใช้เวลานานกว่า Google มองแท็ก <link rel="canonical"> เป็นเพียงคำแนะนำ ไม่ใช่คำสั่งที่บังคับ ถ้า URL เก่ามี backlink และข้อมูลคลิกสะสมมากกว่า Google อาจยังเลือกเป็น canonical ต่ออีกหลายสัปดาห์

การผสมผสานระหว่าง redirect ที่สะอาด, sitemap เดียวที่น่าเชื่อถือ และ GSC property ที่รวมเป็นหนึ่งเดียว จะส่งสัญญาณที่ชัดเจนที่สุดให้ Google ในกรณีของเรา คำเตือน "Duplicate canonical" เริ่มลดลงภายในสองสัปดาห์หลัง deploy การแก้ไขเหล่านี้

เราดูแลการย้ายเว็บลักษณะนี้เป็นประจำในฐานะส่วนหนึ่งของงาน performance และการย้าย WordPress ของเรา ถ้าคุณกำลังเผชิญปัญหา SEO หลังการย้ายเว็บ ติดต่อเราได้เลย


บทความที่เกี่ยวข้อง

บทความที่เกี่ยวข้อง