สารบัญ
สถานะการแก้ไข (26 ต.ค.)
เทียบกับ PDF ทีละข้อ
สรุปสำหรับผู้บริหาร
Technical SEO และการ crawl
Metadata
Structured data และ entity
AEO / การมองเห็นบน AI
Content
Structure และ UX
แผนปฏิบัติการ
แหล่งข้อมูล
คำอธิบายศัพท์
00 · อัปเดต 26 ตุลาคม 2026
สถานะการแก้ไข
สรุปงานที่ทำไปแล้วหลังได้รับ audit: แก้เหตุรูปเสียทั้งเว็บที่ WAF (ขึ้นระบบแล้วทั้ง prod และ UAT) และแก้โค้ด P1 รอบแรกบน branch feature/seo-audit ซึ่งขึ้น prod แล้ว 26 ต.ค. (DB migrate แล้ว · ยังไม่ได้รัน backfill) — canonical ภาษาไทย/จีน (T1, T4) ตัดสินใจและแก้แล้ว 21 ต.ค. SEO แยกตามภาษา (Option A) ตัดสินใจและเขียนโค้ดครบ 3 repo แล้ว 21 ต.ค. ลิงก์จอง (#7) แก้แล้ว 21 ต.ค. และ noindex ของ UAT (T3) แก้แล้ว 22 ต.ค.
887/887
รูปจาก CMS บน prod โหลดได้หลังแก้ WAF (เดิม 403 ทั้งหมด)
812/812
รูปบน UAT โหลดได้หลังแก้ WAF
58 → 443
จำนวนคำใน HTML จาก server ของหน้าแรก (EN)
114/116
เทสใน Chrome (19 หน้า, hero, จอ 6 ขนาด, drawer, ลิงก์จอง) — 2 ข้อที่เหลือเป็นตามดีไซน์
9.4 → 6.9 วิ
LCP หน้าแรกบนมือถือ (Slow 4G) วัดบน prod ก่อน/หลัง deploy · คะแนน 32–34 → 57 · CLS 0.80 → 0
2.5 → 1.7 MB
น้ำหนักหน้าแรกบนมือถือ (prod ก่อน → หลัง deploy) · desktop ยัง ~8.4 MB จนกว่าจะอัปโหลดวิดีโอ hero ที่บีบอัดแล้ว (เหลือ ~2 MB)
0
บั๊กใหม่จากโค้ดรอบนี้ที่เจอบน prod หลัง deploy (25 agent ทดสอบ 26 ต.ค. · ดูข้อ 2f)
7
commit บน feature/seo-audit (web 4 · api 2 · cms 1) · ขึ้น prod แล้ว 26 ต.ค. (API 20:14 · เว็บ 20:29 · CMS 20:30)
1
เรื่องที่รอตัดสินใจ — รายการลิงก์ใน footer (ดูข้อ 3)
1) เหตุด่วน: รูปจาก CMS เสียทั้งเว็บ — แก้แล้ว ขึ้นระบบแล้ว
อาการ: รูปห้อง F&B บล็อก และ facility บน www.yanhhotel.com ไม่ขึ้น ส่วนรูป static ของเว็บยังปกติ (ไม่เกี่ยวกับ audit แต่เจอระหว่างตรวจ)
สาเหตุ (ยืนยันจาก Cloud Logging): Cloud Armor rule 10000 ส่วน rfi-v33-stable signature owasp-crs-v030301-id931130-rfi เริ่มบล็อกทุก request ที่ query string มี URL แบบ https:// — Next.js ย่อรูปผ่าน /_next/image?url=https://storage.googleapis.com/... จึงโดนทุกรูป
เวลา (UTC) สิ่งที่เกิด
ถึง 16 ต.ค. 05:00 รูปผ่าน WAF ปกติ 100% (ไม่มีการบล็อกเลย)
16 ต.ค. 05:12 – 17 ต.ค. 05:04 ผ่านบ้าง โดนบ้าง ปนกันข้ามหลาย IP — ลักษณะการทยอย rollout
ตั้งแต่ 17 ต.ค. 05:05 โดนบล็อก 100% (13–20 ต.ค. บล็อก 4,863 ครั้ง จาก 349 IP)
20 ต.ค. 14:49 → มีผล 14:52 เพิ่ม rule 9700 บน policy prod scx-yanhhotel-prod-waf-bkk-001
21 ต.ค. 08:35 → มีผล 08:36 เพิ่ม rule 9700 บน policy UAT scx-yanhhotel-dev-waf-bkk-001 (regex รวม files-uat.yanhhotel.com)
ฝั่งเราไม่มีใครแก้ policy ตั้งแต่ 30 ก.ค. ไม่มี admin activity ใน project ช่วง 14–18 ต.ค. และเว็บ deploy ครั้งล่าสุดคือ 28 ก.ย. — สรุปว่าเป็นการอัปเดต signature ฝั่ง Google (อนุมานจากรูปแบบใน log ยังไม่พบประกาศทางการ)
rule 9700 (action allow, มาก่อน rule 10000) อนุญาตเฉพาะคำขอย่อรูปที่ชี้ไปโดเมนรูปของเราเท่านั้น และไม่ผูก host ของเว็บ (บทเรียนจาก rule 9600 ที่พังตอน go-live):
request.path == "/_next/image" && request.method == "GET" &&
request.query.matches("^url=https%3A%2F%2F(?:storage\\.googleapis\\.com|files(?:-prod-gcp)?\\.yanhhotel\\.com)%2F[^&]+&w=[0-9]+&q=[0-9]+$")
ผลตรวจหลังแก้: prod รูปจาก 8 หน้าหลัก 887/887 URL ได้ 200 · UAT 812/812 · WAF ยังบล็อก URL ใน query ของหน้าอื่น, โดเมนรูปที่ไม่รู้จัก และ query ที่มีพารามิเตอร์แปลกปลอมเหมือนเดิม ถ้าเพิ่มโดเมนรูปใหม่ในอนาคต ต้องเพิ่มทั้งใน next.config.ts (images.remotePatterns) และใน regex ของ rule 9700 ทั้ง prod และ UAT
2) แก้โค้ด P1 รอบแรก — branch feature/seo-audit (ขึ้น prod แล้ว 26 ต.ค.)
Branch แตกจาก origin/uat (bf66065 = โค้ดบน prod ก่อนรอบนี้) เพราะ dev ตามหลัง uat 27 commits · ผลตรวจ: tsc 0 error, eslint 0 error 0 warning, next build ผ่าน, runtime check กับ API prod ผ่าน 48/48, review diff ครบ · ลิงก์จองและรูปแบบ title ที่ให้คงไว้ เทียบกับ prod แล้วไม่เปลี่ยน · hreflang เหมือน prod ทุกตัว
Audit สิ่งที่แก้ สถานะ
T1 / #1, T4 / #4 ทุกหน้า canonical เป็น URL ของตัวเองในภาษาของตัวเอง (/th/our-story → /th/our-story เดิมชี้ /en/our-story) — เว็บเลิกอ่าน Canonical URL จาก CMS ซึ่งเป็นค่าเดียวที่ฝัง /en/ · canonical ที่ชี้หน้า 404 (/en/blog-and-review, /en/media-influencer-request) หายไปด้วย · og:url และ url ใน JSON-LD ตรงกับ canonical · hreflang ไม่เปลี่ยน (ตัดสินใจ 21 ต.ค.) ขึ้น prod แล้ว
#8 SEO แยกภาษา (Option A) yanh-api: เพิ่ม meta_title/meta_description/meta_keywords ในตารางแปลภาษา 16 ตาราง (เก็บคอลัมน์เดิมไว้ rollback) · service เขียน SEO ลงแถวของ languageCode · duplicate ภาษาใหม่ไม่คัดลอก SEO · SQL ย้ายข้อมูลเดิมตามอักษรที่เขียน (ไทย → TH, อื่นๆ → EN) + preview · แก้ DTO ห้องพักที่ไม่รับ metaImageyanh-cms: การ์ด SEO กลาง (SeoFields/SeoDetailFields) แทน 15 ชุดที่ copy · Title/Description/Keywords แยกตามภาษา (ไอคอนลูกโลก) · เพิ่มการ์ด SEO ให้ห้องพัก · ความยาวแบบ Bridge: แนะนำ 60–70 / 140–175 เตือนสีเหลือง บังคับแค่ 255/500yanh-web: อ่าน SEO จากแถวภาษาของหน้า ถ้าว่างใช้ชื่อหน้าภาษานั้น + suffix ตาม PDF (Rooms | YANH Ratchawat Hotel, Bangkok, ห้องพัก | โรงแรมย่าน ราชวัตร ดุสิต กรุงเทพฯ, 客房 | YANH Ratchawat 曼谷酒店) · หน้า privacy/terms อ่าน ogImage ได้แล้วขึ้น prod แล้ว · รอ backfill migrate แล้วทั้ง UAT/prod · เหลือรัน seo-backfill.sql (infra) — ดูข้อ 2f
#7 ลิงก์จอง ทุกลิงก์ไป SiteMinder (การ์ดห้อง, หน้าห้อง, header, banner, ลิงก์จาก CMS) ผ่าน LocaleLink → ตัดวันที่เก่า 29–31 ก.ค. ออก · ใส่ภาษาตามหน้า (th / zh-CN / en) และ currency=THB · คง rateId/จำนวนผู้เข้าพักเดิม · ใส่วันนี้→พรุ่งนี้ (เวลาไทย) ในเบราว์เซอร์หลังโหลดหน้า (HTML จาก server ไม่มีวันที่) · ส่ง event booking_click เข้า dataLayer · date picker ใน header เลื่อนไปทำทีหลัง ขึ้น prod แล้ว ยังต้องให้ marketing ลองสลับภาษาไทย/จีนใน engine ว่า property เปิดไว้
Hydration error (เจอตอนเทส) หน้ารายการห้อง, F&B และการ์ด blog/ย่าน วาง HTML จาก CMS (มี <p>) ลงใน <p> อีกชั้น → React error #418 (มีบน prod อยู่แล้ว) · เปลี่ยนเป็น <div> 5 จุด หน้าตาไม่เปลี่ยน · เทสซ้ำไม่มี hydration error ทุกหน้า ขึ้น prod แล้ว
T3 / #3 UAT ถูก index next.config.ts ส่ง X-Robots-Tag: noindex, nofollow ทุก response เมื่อโดเมนไม่ใช่ www.yanhhotel.com (www-uat, www-prod-gcp, *.run.app) · ยืนยันจาก log ของ Cloud Run แล้วว่า LB ส่งชื่อโดเมนจริงถึงแอป · เทสแล้ว: www.yanhhotel.com ไม่มี header ทุก path · robots.txt ยังเปิดให้ crawl เพื่อให้ Google เห็น noindexขึ้น prod แล้ว ต่อ: marketing ลบ URL UAT ใน Search Console → infra ตั้ง IAP/รหัสผ่าน
T2 / #2 robots.txt ชี้ Sitemap: https://www.yanhhotel.com/sitemap.xml (เดิมชี้ www-uat)ขึ้น prod แล้ว
T5 / #5 ลิงก์ภายในทุกจุดติดภาษาของหน้า (helper localizeHref() + LocaleLink) รวมการ์ดห้อง, footer, ปุ่ม Learn More, ฟอร์ม, ปุ่ม hero จาก CMS · breadcrumb Home ไม่มี / ท้าย (ตัด 308) · ESLint ห้ามใช้ next/link ตรงๆ กันลิงก์หลุดภาษาในอนาคต ขึ้น prod แล้ว
#6 หน้าแรก เมนู และ footer render ฝั่ง server: เนื้อหาหน้าแรกอยู่ใน HTML (58 → 443 คำ), เมนู desktop อยู่ใน HTML ทุกขนาดจอ, footer มีที่อยู่ อีเมล เบอร์โทร และลิงก์ Cookies Policy · "Copyright undefined" หายแล้ว · รายการลิงก์ใน footer: PDF (หน้า 12 แถว Footer) สั่งแค่ "address, phone, LINE, key pages" ไม่ได้ระบุว่าหน้าไหน — แนวทางของผู้แก้ · ไม่อยู่ใน PDF ใส่ทุกหน้าในเมนู (8 ลิงก์ ซ้ำกับเมนู header 5 ลิงก์) + 6 หน้า F&B/ห้องประชุม เพื่อให้หน้า orphan มีลิงก์เข้าชั่วคราว (วิธีตาม PDF คือ hub ในเมนูหลัก + tile ใน Facilities = #12) · หน้าตายังไม่ผ่านดีไซน์ — รอตัดสินใจ (ข้อ 3) ขึ้น prod แล้ว
NAP / Contact หน้า Contact กลับมาแสดงชื่อและที่อยู่โรงแรม (บั๊กเดิม: โค้ดอ่าน translation แต่ API ส่ง translations[]) ขึ้น prod แล้ว
#9 JSON-LD: Hotel + WebSite ทุกหน้า, HotelRoom หน้าห้อง, BreadcrumbList หน้าภายในทุกหน้า · ไม่มี AggregateRating · ค่าที่โรงแรมยังไม่ยืนยัน (geo, จำนวนห้อง, check-in/out, amenities) เว้นไว้ ขึ้น prod แล้ว
#8 (ส่วนโค้ด) H1 เดียวต่อหน้า (หน้าแรกมี H1, หน้า F&B/ห้องประชุมใช้ชื่อสถานที่จริง, Cookies Policy H1 และแท็บถูกต้อง, Terms ใช้ชื่อจาก CMS) · ตัด zero-width (U+200B) ออกจาก title/H1/JSON-LD · description ไม่ซ้ำ title · fallback title ห้องประชุม/F&B เป็นชื่อสถานที่ + ความจุ · og:site_name = "YANH Ratchawat" ขึ้น prod แล้ว title ภาษา TH/ZH + suffix: ดูแถว Option A
บั๊กที่เจอระหว่างทาง "Other rooms" มีห้องตัวเองปน · รูปมี alt="t" · ข้อความ debug "Contact Page TH" ก่อน H1 ใน 16 หน้า · <a> ซ้อนใน <button> · หน้า 404 ใช้ภาษาตาม URL · การ์ด neighbourhood ที่ลิงก์ # ไม่เป็นลิงก์ตาย ขึ้น prod แล้ว
ความเป็นส่วนตัว / ภาระ API ไม่ส่งข้อมูลดิบจาก CMS (มีชื่อคนแก้ข้อมูล) ไปฝั่ง client · เลิกเรียก /api/home-setting, /api/hero-banner, /api/general-nav, /api/contact จากเบราว์เซอร์ทุกครั้งที่เปิดหน้า (ถอด swr) ขึ้น prod แล้ว
CSP (เจอบน prod 21 ต.ค.) (1) อนุญาต <style> ที่ vaul (drawer เมนู) ฉีดเองด้วย hash — เดิมถูกบล็อก animation ของเมนูจึงหาย (2) เพิ่ม https://analytics.google.com ใน connect-src — เดิม hit ของ GA4 ที่ไป /g/collect ถูกบล็อก ขึ้น prod แล้ว
2b) Performance (#15) — ขึ้น prod แล้ว 26 ต.ค. (รอทีม content อัปโหลดวิดีโอ)
วัดด้วย Lighthouse ที่หน้าแรก /en · "Slow 4G" คือจำลองเน็ตช้าจริง (--throttling-method=devtools) ซึ่งวัดวิดีโอได้ตรงกว่าแบบประเมิน
prod วันนี้ (โค้ดเก่า) ก่อนงานนี้ (มี P1) หลังงานนี้ + วิดีโอใหม่
Mobile: คะแนน / LCP 40 / 19.3 วิ 75 / 6.4 วิ 78 / 5.7 วิ 80 / 5.1 วิ
Mobile LCP (Slow 4G) — 9.1 วิ 3.7 วิ (localhost) วัดหลังอัปโหลด
UAT จริง 26 ต.ค. (มือถือ Slow 4G)prod: 32–34 / LCP 9.4–10 วิ / CLS 0.80 UAT: คะแนน 59–60 / LCP 6.9 วิ / CLS 0 · desktop 96–97 (prod 65–69) — ตัวเลข preview ด้านบนวัดบน localhost (HTTP/1.1 ไม่มี GTM) จึงมองดีเกินจริง · LCP ที่เหลือคือวิดีโอ hero ที่ยังเป็นไฟล์เดิม
prod จริงหลัง deploy 26 ต.ค. (มือถือ Slow 4G)ก่อน deploy: 32–34 / LCP 9.4–10 วิ / CLS 0.80 / 2.52 MB หลัง deploy: คะแนน 57 / LCP 6.86 วิ / CLS 0 / 1.73 MB · desktop 96–97 (เดิม 65–69) แต่ยังหนัก 8.4 MB เพราะวิดีโอ hero ไฟล์เดิม 7.6 MB
CLS mobile / desktop 0.80 / 0.70 0 / 0 0 / 0 0 / 0
Desktop: คะแนน 69 97 99 99
น้ำหนักหน้า mobile / desktop 9.9 / 9.5 MB 1.8–2.2 / 9.1 MB 1.1–1.5 / 8.4 MB 1.2 / 2.0 MB
เรื่อง สิ่งที่แก้ สถานะ
Instagram (เคยหนัก ~8 MB) ดึง feed ฝั่ง server เหลือ 6 โพสต์ตาม PDF · รูปย่อผ่าน next/image ทาง route ของเราเอง (รูปละ 0.4–2 MB → ~30 KB) เพราะ URL ของ Instagram ใน query ถูก WAF บล็อก · โหลดเมื่อเลื่อนถึง · โพสต์วิดีโอใช้ภาพปกแทนการโหลดคลิป · alt อ่านได้ (แปลงตัวหนา Unicode เป็นตัวปกติ) ขึ้น prod แล้ว yanh-api ขึ้นแล้ว: โพสต์วิดีโอแสดงเป็นภาพปกบน prod
Hero / LCP วิดีโออยู่ใน HTML จาก server เบราว์เซอร์เลือกไฟล์มือถือ/desktop เอง (เดิมรอ JS วัดจอหลังโหลดหน้า) · section ไม่ถูกซ่อนรอ animation แล้ว (animate เฉพาะข้อความ) · preconnect ไปโดเมนของวิดีโอ ขึ้น prod แล้ว
ไฟล์วิดีโอ hero desktop 7.8 MB → 1.3 MB (ตัด audio เปล่า, บีบอัดใหม่ ภาพแทบไม่ต่าง — มี overlay ดำ 70% ทับ) · ทั้ง 2 ไฟล์ทำ faststart — ไฟล์เดิมทำให้เบราว์เซอร์โหลดซ้ำ (mobile 340+287 KB, desktop 6.1+2.0 MB) · ไฟล์อยู่ที่ hero-video-optimized/ งาน content อัปโหลดแทนไฟล์เดิมใน CMS → Hero Banner
ฟอนต์ / cache ฟอนต์หัวข้อย้ายไป next/font (cache 1 ปี + fallback ที่ปรับขนาด) · /assets/* cache 7 วัน (เดิม 0) · รูปที่ย่อแล้ว cache 31 วัน (เดิม 4 ชม.) · ไฟล์ที่อัปโหลดเข้า GCS ใหม่ได้ cache 1 ปี (yanh-api) ขึ้น prod แล้ว ไฟล์เก่าใน bucket ต้องให้ infra ตั้ง cache (ต้องอนุมัติ)
ขนาดรูป / alt แก้ sizes ของรูปที่ขอใหญ่เกิน (พื้นหลังย่านเคยขอกว้าง 3840 px, Our Story, โลโก้) · รูปตกแต่งเป็น alt="" แทน "Our Story Image 01", "line 01" ขึ้น prod แล้ว
ลองแล้วไม่ใช้ inlineCss ของ Next.js — HTML บวม 228 KB → 1 MB และ <style> ไม่มี nonce ทำให้ CSP บล็อกทั้งหน้าไม่ทำ
ยังเหลือ CSS 5 ไฟล์ที่บล็อก render (~0.3 วิ บน Slow 4G) — อยู่ใน PDF แต่ทางเดียวของ Next.js คือ inlineCss ซึ่งชนกับ CSP บางส่วน
ไม่ทำ (นอก PDF) ช่อง poster ของ hero ใน API/CMS (PDF ไม่ได้สั่ง — LCP ≤ 2.5 วิ เป็นแค่เกณฑ์ในตารางคะแนน) · JS ที่ไม่ได้ใช้ ~48 KB · TTFB 0.5–0.7 วิ (CSP nonce ทำให้ cache HTML ไม่ได้) ไม่ทำ
2c) P2 ชุดที่ไม่ต้องเพิ่มระบบ — ขึ้น prod แล้ว 26 ต.ค.
ทำด้วยข้อมูลที่ CMS/API มีอยู่แล้วทั้งหมด ไม่มีตาราง ฟิลด์ หรือ module ใหม่ · ตรวจด้วย build + Chrome headless กับ API prod
Audit สิ่งที่แก้ สถานะ
#17 / T6 sitemap ใช้วันที่แก้ไขจริงจาก CMS (ตัวหลัก + แถวภาษาของหน้านั้น หน้ารวมนับรายการที่แสดงด้วย) แทนวันนี้ · ไม่มีวันที่ก็ไม่ใส่ lastmod · sitemap index ใช้วันล่าสุดของแต่ละไฟล์ — ตรวจแล้วไม่มี URL ไหนเป็นวันนี้ ขึ้น prod แล้ว
#14 + Article Restaurant (TANH) / CafeOrCoffeeShop (Groundwork) พร้อมเวลาเปิด · MeetingRoom 4 ห้อง (ความจุ พื้นที่ อุปกรณ์) · Article ในบทความ blog และย่าน · ทุกตัวผูก containedInPlace/author กับ Hotelขึ้น prod แล้ว servesCuisine เว้นไว้ — CMS ไม่มีข้อมูล
#16 og:image ทุกหน้า: รูป SEO จาก CMS ก่อน ถ้าว่างใช้รูป header ของหน้า หรือรูปของห้อง/venue/บทความนั้น · หน้า PDPA ใช้รูป SEO ของหน้าแรก ขึ้น prod แล้ว
#23 + T9 ฟอร์มสื่อย้ายไป /press — URL เดิม 301 ไปที่ใหม่ (เมนู, sitemap อัปเดตแล้ว) · path ที่ไม่รู้จัก (/llms.txt, /cn, /sitemap_index.xml) ได้ 404 แทน redirect ไปหน้าแรก ขึ้น prod แล้ว
T7 (ชั่วคราว, 26 ต.ค.) slug ไม่แยกตัวพิมพ์แล้วทั้ง 5 แบบหน้า (ห้อง, F&B, ห้องประชุม, blog, ย่าน): /food-and-drink/tanh → /food-and-drink/TANH (307) แทน 404 · URL หลักยังไม่เปลี่ยน — การย้ายไป /dining/tanh, /meetings/tanh-2nd-floor + 301 ตาม PDF ทำพร้อม #12 เพื่อให้ย้ายครั้งเดียว · ใช้ 307 ไม่ใช่ 301 เพราะเป็นของชั่วคราว (301/308 ถูกเบราว์เซอร์จำค้าง) บางส่วน
#19 alt text (26 ต.ค.) ไล่ alt ทั้ง 90 จุดในโค้ด แก้ 66 จุดใน 29 ไฟล์: พื้นหลัง/ภาพตกแต่ง (เช่น "Our Story Image 02–06" ในหน้า Our Story, "Contact Image 01–03") และไอคอนที่มีชื่อเขียนอยู่ข้างๆ → alt ว่าง · รูปร้าน/ห้อง/facility/บทความใช้ชื่อจริง (เช่น "GROUNDWORK Specialty Coffee", "Fitness 1") · ปุ่ม gallery และปุ่มแชร์มีชื่อ · แก้บั๊ก InnerHeader ที่ส่ง alt ว่างแล้วได้ "Inner header image" · ตัด HTML จากชื่อใน CMS ("Worth the Night<br/> …") ขึ้น prod แล้ว
#19 (ส่วน dev) ปุ่มไอคอนที่ไม่มีชื่อ (ปิด cookie banner, ปิดหน้าตั้งค่า cookie, ปิด VR) ได้ชื่อแล้ว · alt="X" ของปุ่มแชร์ Instagram แก้ · Lighthouse accessibility 89 → 95–96 ทุกหน้า บางส่วน contrast = สีแบรนด์ รอดีไซน์
2d) ผลทดสอบ 26 ต.ค. — โค้ดที่ push แล้ว
ทดสอบบนเครื่องจาก origin/dev (web f19f4ae, api 1e58e02) และ origin/develop (cms 952943b): เว็บอ่าน API prod แบบอ่านอย่างเดียว · API/CMS รันกับ Postgres ทดลองใน Docker · 44 agent แยก 9 ด้าน และทุกข้อที่ไม่ผ่านมี agent อีกตัวทำซ้ำเพื่อยืนยัน · ไม่แตะ UAT/prod นอกจากอ่าน
ด้าน ผล
SEO head (81 URL) canonical, hreflang, og:url, og:image, H1, lang, X-Robots-Tag ผ่าน 81/81 · เทียบ prod: canonical ถูก 41→81, og:image 6→81, หน้าที่มี JSON-LD 0→81
JSON-LD (159 block) parse ได้ทุก block · validator.schema.org 0 error (18 หน้า) · ความจุ/พื้นที่ห้องประชุม และเวลาเปิดร้านตรงกับ API
Routing / ลิงก์ 482 กรณี redirect/status ผ่าน (รวม slug ตัวพิมพ์ 402 กรณี) · ลิงก์ภายใน 4,089 ตัวติด locale ถูก ไม่มีลิงก์เสีย · lastmod ตรงวันที่แก้ใน CMS ทุก URL
เบราว์เซอร์ 90 การโหลดหน้า (en ทุกหน้า + th/zh): hydration error 0, CSP 0, request ล้มเหลว 0, ลิงก์จองถูกทุกจุด
Unit test helper 1,355 assertion — ที่ตกเป็น 2 บั๊กเล็กที่ยังไม่เกิดกับข้อมูลจริง
Migrate + backfill schema ใหม่ = 16 ALTER TABLE / 48 ADD COLUMN เท่านั้น · db push บน DB ที่มีข้อมูลไม่ลบอะไร · backfill ย้ายค่าถูกภาษา และรันซ้ำได้ · API ทำงานหลัง migrate และพังด้วย error เดียวกับ UAT ถ้ายังไม่ migrate
API 16 entity 382 check: SEO ลงแถวภาษาที่ถูกทุก entity, แถวอื่นและคอลัมน์เดิมไม่เปลี่ยน, duplicate ไม่คัดลอก SEO
CMS → API → เว็บ 6 ฟอร์ม 146/146 + อีก 10 entity 78/78 · หน้า /zh ที่ไม่มีค่าใช้ fallback ไม่ยืมภาษาอื่น
Performance preview บน localhost: LCP 4.1–4.3 วิ — มองดีเกินจริง · UAT จริง: LCP 6.9 วิ (prod 9.4–10), คะแนน 59–60 (prod 32–34), CLS 0 (prod 0.80), desktop 96–97 (prod 65–69)
บั๊กจากงานรอบนี้ (ยืนยันแล้ว — ยังไม่ได้แก้)
ระดับ เรื่อง ที่
medium ขั้นตอน migrate ในเอกสารไม่มี --build → รัน image เก่า ไม่เพิ่มคอลัมน์แต่ขึ้นว่าสำเร็จ (แก้ในเอกสารแล้ว · comment ในไฟล์ SQL ยังต้องแก้) เอกสาร + yanh-api/prisma/sql
low หน้า 404 ของ locale ที่ไม่มี (/cn) ปุ่ม Back to Home ชี้กลับ /cn src/app/not-found.tsx
low redirect slug ตัวพิมพ์ (T7) ตัด query string (UTM หาย) src/lib/slug.ts
low /llms.txt, /foo.png ได้ 404 ถูกต้อง แต่แสดงเป็นหน้าขาวsrc/middleware.ts
low ตัด fallback title นับ UTF-16 ไม่ใช่ตัวอักษรที่เห็น และอาจตัดกลางสระ/วรรณยุกต์ (ยังไม่เกิดกับข้อมูลจริง) src/lib/utils.ts
low Restaurant / CafeOrCoffeeShop ไม่มี address (Rich Results จะฟ้อง) src/lib/jsonld.ts
low อ่านเวลาเปิดแบบ "a.m./p.m." (มีจุด) ผิด — ข้อมูลตอนนี้ไม่มีรูปแบบนี้ src/lib/jsonld.ts
low POST /home-setting/save ไม่ atomic: SEO ยาวเกิน 255 ได้ 500 แต่ค่าบางส่วนถูกบันทึกไปแล้ว (CMS จำกัดความยาวไว้ จึงเกิดเฉพาะเรียก API ตรง)home-setting.service.ts
low backfill: เช็คค่าว่างไม่นับช่องว่างพิเศษ (NBSP, zero-width) · regex ไทยนับ ฿ เป็นภาษาไทย (ข้อมูลจริงไม่โดน) prisma/sql/*.sql
ปัญหาเดิม (มีบน prod อยู่แล้ว) ที่เจอจากการทดสอบ — ไม่อยู่ใน PDF
CMS (medium): ฟอร์ม Home Setting และ Contact ถ้า refresh หน้า edit ภาษาไทยแล้วคำตอบภาษาอังกฤษมาช้ากว่า ฟอร์มจะแสดงค่าอังกฤษ และกด Save จะเขียนทับแถวภาษาไทย — เดิมโดนแค่ชื่อ/ที่อยู่ ตอนนี้โดน SEO ด้วย · 2 ฟอร์มนี้ไม่มีตัวกันคำตอบเก่าแบบอีก 25 ฟอร์ม
หน้า /zh ที่ไม่มีแถวภาษาจีน ใช้แถวแรกที่ DB ส่งมา (อาจเป็นภาษาไทย) · title/og:title ยังมี HTML จากชื่อใน CMS (เช่น <br/>)
Accessibility (axe): สวิตช์ใน cookie settings ไม่มีชื่อ · drawer เมนูเปิดจาก keyboard แล้วโฟกัสหลุด · iframe VR/แผนที่ไม่มี title · animation ข้อความใส่ aria-label บน div · tab ในหน้ารายละเอียดชี้ panel ที่ไม่มี · dialog แพ็กเกจห้องประชุมเลื่อนด้วย keyboard ไม่ได้
วิดีโอ Facebook ในหน้าย่านเปิดไม่ได้ · ข้อความ "soft lightstay" ติดกันบนมือถือ
ตามที่ตั้งใจ: brand suffix ต่อท้าย title จาก CMS ที่ยังไม่มีชื่อโรงแรมเมื่อยังพอที่ (ไม่ตัด title จาก CMS) · title fallback ที่ยาว 54–60 ตัวอักษรไม่มี suffix · ข้อมูล CMS ที่ผิดภาษา/ซ้ำ อยู่ในแท็บงานที่ไม่ใช่ Dev
2e) ทดสอบบน UAT จริง 26 ต.ค. — อ่านอย่างเดียว
UAT รันโค้ดชุดเดียวกัน (web f19f4ae, api 1e58e02) · DB migrate แล้วแต่ยังไม่ backfill · 24 agent ใช้ GET อย่างเดียว ≤2 request/วินาที · ไม่โดน Cloud Armor บล็อกเลย
ด้าน ผล
SEO head + JSON-LD ตรงกับรอบ local ทั้ง 81 URL · รันโค้ดจริงกับข้อมูล API UAT ได้ผลตรงกับ HTML ที่ deploy 81/81 · ใช้ title fallback ถูกต้องระหว่างยังไม่ backfill · JSON-LD parse ได้ 159/159
Routing / ลิงก์ redirect, 404, slug ตัวพิมพ์ ผ่าน LB จริงเหมือน local · ลิงก์ภายในติด locale ถูก
เบราว์เซอร์ hydration error 0 · 4xx/5xx 0 · WAF block 0 (รวมรูปที่ย่อ, รูป Instagram, วิดีโอ hero) · โพสต์วิดีโอ Instagram แสดงเป็นภาพปกแล้ว · ลิงก์จอง, cookie banner, drawer, /press, 404 ผ่าน · หน้าจอไม่มี layout พังเทียบ prod
API UAT 68/68 ตอบ 200 · แถวแปลภาษามีช่อง SEO ครบ (ยังว่าง) · backfill dry run: จะเติม 15 ช่องใน 8 entity (ลงแถว en ทั้งหมด) ไม่มี skip — ค่าเดิมบน UAT เป็นค่าทดสอบ (เช่น "Privacy Policy | SCX") หลัง backfill title บน UAT จะเป็นค่านั้น
Performance หน้าแรกมือถือ LCP 6.9 วิ (prod 9.4–10), คะแนน 59–60 (prod 32–34), CLS 0 (prod 0.80) · desktop 96–97 (prod 65–69) · cache header ผ่าน LB ตรงตามที่ตั้ง
เจอเฉพาะบนสภาพแวดล้อมจริง (ไม่ใช่โค้ดรอบนี้): http:// ไม่ redirect ไป https ทั้ง UAT และ prod (medium, infra) · Cloud Armor บล็อกไฟล์ CMS /assets/500--bpmkw88.js (low, infra) · HEAD ไป /_next/image ได้ 403 เพราะ rule 9700 อนุญาตแค่ GET (low) · GA4 ทำงานก่อนผู้ใช้ยินยอม และ CSP บล็อก GA4 Google Signals (มีบน prod เดิม) · reCAPTCHA error ตอนสลับภาษาหน้าฟอร์ม (มีบน prod เดิม)
ข้อมูล UAT: Home Setting บน UAT ไม่มี SEO image จึงไม่มี og:image ที่หน้าแรก/PDPA (prod มี) · การ์ดย่าน link-out บน UAT ชี้ไปหน้าที่ไม่มี 12 ลิงก์ · บั๊ก low จากรอบ local เจอซ้ำบน UAT เหมือนเดิม
2f) ทดสอบบน prod จริง 26 ต.ค. — อ่านอย่างเดียว หลัง deploy
prod รันโค้ดชุดเดียวกับ UAT (web f19f4ae, api 1e58e02, cms 952943b) · DB migrate แล้วแต่ยังไม่ backfill · 25 agent ใช้ GET อย่างเดียว (ใน browser ตัด POST ทุกตัว hit ของ GA ไม่ถึง property จริง) ≤1.5 request/วินาที · ไม่โดน WAF บล็อกจากการใช้งานปกติ (403 ที่เจอมีแค่ตอนตั้งใจทดสอบ HEAD /_next/image ซึ่งเป็นปัญหาที่รู้อยู่แล้ว) · ผลเหมือน local และ UAT — ไม่เจอบั๊กใหม่จากโค้ดรอบนี้
ด้าน ผล
SEO head + JSON-LD (81 URL) canonical, hreflang, og:url, og:locale, lang, H1 ผ่าน 81/81 · รันโค้ดจริง (buildSeo) กับข้อมูล API prod ได้ผลตรงกับ HTML ที่ deploy 81/81 · ใช้ title fallback ตามที่ออกแบบระหว่างยังไม่ backfill · JSON-LD parse 159/159 · ความจุห้องประชุม 12/12 และเวลาเปิดร้าน 6/6 ตรง API · og:image 24 ไฟล์โหลดได้ทั้งหมด · bot 7 ตัว (Googlebot, Bing, Facebook, Twitter, LINE, GPTBot, curl) ได้ 200 ไม่โดน WAF
X-Robots-Tag ไม่มีบน www ทั้ง 771 response (หน้า, 404, redirect, robots, sitemap, asset, รูป) · มี noindex, nofollow บน www-prod-gcp ทุกครั้ง
Routing / ลิงก์ 482/482 กรณีตรงกับ local · sitemap 81 URL ได้ 200 · lastmod ตรงวันที่แก้ใน API 81/81 · ลิงก์ภายใน 4,089 ลิงก์ติด locale ถูก
API / CMS prod 68/68 ตอบ 200 (5xx ช่วง deploy 20:13–20:16 หายแล้ว) · p50 102 ms · เทียบ snapshot ก่อน deploy: ไม่มีช่องหายหรือค่าเปลี่ยน มีแค่ช่อง SEO ในแถวแปลภาษาและ thumbnailUrl เพิ่ม · CMS prod เป็นโค้ดใหม่ ไฟล์ JS 22/22 โหลดได้
เบราว์เซอร์ 46 หน้า + ~60 การโหลด: hydration error 0, 4xx/5xx 0, WAF block 0 · วิดีโอ hero เล่นทั้ง desktop/mobile และสลับที่ 767/768 px · Instagram 6 โพสต์ผ่าน proxy (รวมโพสต์วิดีโอ) · ลิงก์จอง 96/96 · cookie banner, drawer, สลับภาษา, /press, 404 ผ่าน · เทียบภาพกับ prod ก่อน deploy: layout ไม่พัง ต่างแค่ footer (หน้ายาวขึ้น 380–440 px), ชื่อสถานที่ในหัวหน้า และ breadcrumb ของ /press
Performance หน้าแรกมือถือ: คะแนน 57 (ก่อน deploy 32–34), LCP 6.86 วิ (9.4–10), CLS 0 (0.80), 1.73 MB (2.52) · desktop 96–97 (65–69) · หน้าห้อง/TANH มือถือ 80–83, desktop 98 (เท่าเดิม) · ไม่มี cold start
ขนาดตัวอักษร (ตรวจเพิ่ม) build prod เดิม (bf66065) เทียบกับ prod ใหม่ 7 หน้า × 3 ขนาดจอ: ขนาด น้ำหนัก line-height และความกว้างข้อความเท่ากันทุกจุด — การย้ายฟอนต์ Oregon LDO ไป next/font ไม่ได้ทำให้ตัวอักษรเปลี่ยน
ต้องจัดการ
backfill (infra): dry run บนข้อมูล prod จะเติม 15 ช่อง (13 ลงแถว en, 2 ลงแถว th) ไม่มี skip · เปลี่ยนแค่ 5 หน้าภาษาอังกฤษ (/en, /en/contact, /en/press, /en/privacy-policy, /en/terms-and-conditions) · ข้อควรรู้: title หน้าแรกจะเปลี่ยนจาก "YANH Ratchawat Hotel, Dusit, Bangkok" กลับเป็นค่าเดิมใน CMS "YANH Ratchawat" และ /en/contact เป็น "Contact | YANH Hotel" → ทีม content ควรกรอก title ใหม่หลัง backfill
ใหม่ · medium Terms & Conditions (content): เนื้อหาทั้ง 3 ภาษาขึ้นต้นด้วยข้อความที่หลงมาจาก ChatGPT ("Below is the revised Website Terms of Use for SCX…") และอ้างถึง SCX · ภาษาจีนเป็นสำเนาภาษาอังกฤษ · อยู่บนหน้ามาก่อนแล้ว แต่ตอนนี้กลายเป็น meta/og description เพราะแถวภาษายังไม่มี SEO · backfill แก้ได้แค่ /en
ใหม่ · medium โดเมนเปล่า yanhhotel.com เข้าไม่ได้ (infra, ไม่ได้เกิดจาก deploy): cert ของ LB มีแค่ *.yanhhotel.com ซึ่งไม่ครอบคลุมโดเมนเปล่า · cert เดิมของ GoDaddy หมดอายุ 19 ต.ค.
วิดีโอ hero บน prod ยังเป็นไฟล์เดิม (content): desktop 7.8 MB, mobile ไม่มี faststart (โหลดซ้ำ 642 KB) — ต้นทุน performance ก้อนใหญ่ที่สุดที่เหลือ
content (low): หน้า neighbourhood 6 หน้าใช้ description เดียวกัน (ข้อความ seed) และฟอร์ม CMS ของรายการย่านไม่มีช่อง description · Hotel description ใน JSON-LD หน้า th/zh เป็นภาษาอังกฤษ (ยังไม่สร้าง web.seo.hotelDescription)
บั๊ก low จากงานรอบนี้: 4 ข้อเดิมในข้อ 2d (/cn Back to Home, UTM หายตอน redirect slug, /llms.txt หน้าขาว, ร้านอาหารไม่มี address) เจอซ้ำบน prod
มีมาก่อนรอบนี้ (ยืนยันกับโค้ดเดิมแล้ว): http:// ไม่ redirect ไป https · HEAD ที่ /_next/image ได้ 403 · GA4 ทำงานก่อนยินยอม และยังส่งแม้กด "ปฏิเสธทั้งหมด" (ไม่มี Consent Mode — ผู้ตรวจปรับเป็น medium เพราะเป็นเรื่อง PDPA) · หน้าย่อยไม่มี <main> · หน้า 404 ของ slug ที่ไม่มี ชื่อแท็บเปลี่ยนเป็นชื่อหน้า detail หลังโหลด (status 404 ถูก) · สลับภาษาหน้าฟอร์มทันทีหลังโหลดจะ reload (reCAPTCHA) · ไม่มี Cloud CDN · ข้อมูล prod 795 URL ยังชี้ bucket ของ dev
3) เรื่องที่รอตัดสินใจ
เรื่อง สถานะปัจจุบัน ข้อเสนอ
รายการลิงก์ใน footer (#6 / Structure: Footer)ขึ้น prod แล้ว: ทุกหน้าในเมนู 8 ลิงก์ + 6 หน้า F&B/ห้องประชุม 3 คอลัมน์ — PDF สั่งแค่ "key pages" ส่วนรายการและหน้าตาเป็นแนวทางของผู้แก้ ยังไม่ผ่านดีไซน์ · พักไว้ 26 ต.ค. แนะนำจากผู้แก้ · ไม่อยู่ใน PDF ก. ตัด 5 ลิงก์ที่ซ้ำกับเมนู header เหลือ Facilities, Blog, Media & Influencer Request + 6 หน้า venue (ทางเดียวที่ crawler เจอหน้าสร้างรายได้จนกว่าจะมี hub) · ข. คงไว้ รอดีไซน์ปรับหน้าตา · ค. เอาออก (6 หน้า venue กลับเป็น orphan จนกว่าจะทำ #12)
4) ก่อนและหลัง deploy (ส่วนของ dev) — deploy prod แล้ว 26 ต.ค.
ตรวจในเบราว์เซอร์: ✅ ทดสอบบน prod หลัง deploy แล้ว (ข้อ 2f) · ก่อนหน้านี้เทสอัตโนมัติด้วย Chrome headless 114/116 (hero, animation, hydration, drawer, จอ 390–1440, ลิงก์จอง, สลับภาษา) · ที่ยังควรดูด้วยตา: ดีไซน์ footer ใหม่ · ยังไม่ได้เทส: การส่งฟอร์ม และหน้าจอ CMS (ต้องมี DB ที่ migrate แล้ว)
ลำดับ deploy ของ SEO แยกภาษา (ทำบน UAT ก่อน แล้ว prod): รัน yanh-api/prisma/sql/seo-backfill-preview.sql (อ่านอย่างเดียว) → backup Cloud SQL → migrate job ต้อง build image ใหม่ จาก commit ที่มี schema ใหม่ (clean checkout ของ origin/uat ตั้งแต่ 1e58e02): UAT ./run-migrate-job.sh --build · prod CONFIRM_PROD_MIGRATE=yes ./run-migrate-job.sh --project=scx-yanhhotel-prod --build · ถ้าไม่ใส่ --build จะรัน image เก่า (schema เดิม) ไม่เพิ่มคอลัมน์แต่ขึ้นว่าสำเร็จ · ห้ามรัน image เก่าหลังเพิ่มคอลัมน์แต่ก่อน backfill เพราะคอลัมน์ใหม่ที่ยังว่างจะถูกลบเงียบๆ → seo-backfill.sql → deploy API → deploy CMS ทันที (ห้ามแก้ SEO ใน CMS ระหว่างนี้) → deploy เว็บ
สถานะ UAT และ prod (26 ต.ค.): uat ถูก merge และ deploy ก่อน migrate → API UAT ตอบ 500 ในส่วนที่มี SEO แยกภาษา · ต่อมา DB ถูก migrate แล้ว (API กลับมา 200) แต่ยังไม่ได้รัน seo-backfill.sql เว็บ UAT จึงยังใช้ title fallback แทนค่าใน CMS · prod: API deploy 20:14 ก่อน migrate job 20:16 → API ตอบ 5xx 114 ครั้งระหว่าง 20:13–20:16 แล้วปกติ · เว็บ 20:29, CMS 20:30 · ยังไม่ backfill · ขั้นต่อไป (ทั้ง 2 ที่): preview SQL → seo-backfill.sql
Commit / merge: เสร็จแล้ว 26 ต.ค. — feature/seo-audit ทั้ง 3 repo push แล้ว และ merge เข้า dev (web, api — api สร้าง dev ใหม่จาก uat) และ develop (cms) · merge เข้า uat และ main แล้ว 26 ต.ค. (web f19f4ae · api 1e58e02 · cms 952943b)
หลัง deploy: ✅ robots.txt, H1, ที่อยู่หน้า Contact, 301 ไป /press, /llms.txt 404 และ JSON-LD parse ตรวจบน prod แล้ว (ข้อ 2f) · ยังเหลือ: Rich Results Test / validator.schema.org — รวมหน้า TANH, ห้องประชุม และบทความย่านที่เพิ่ม schema ใหม่) และส่ง sitemap ใน Search Console · เช็ค /en/blog/media-and-influencer-request ได้ 301 ไป /en/press และ /llms.txt ได้ 404
T3 หลัง deploy: ✅ ตรวจแล้ว (www ไม่มี header, www-prod-gcp มี noindex) · คำสั่งเช็คซ้ำ: curl -sI https://www.yanhhotel.com/th | grep -i x-robots ต้องว่าง และ curl -sI https://www-uat.yanhhotel.com/th | grep -i x-robots ต้องได้ noindex · ขั้นต่อของ marketing และ infra อยู่ในแท็บ งานที่ไม่ใช่ Dev
Performance: ✅ วัดบน prod หลัง deploy แล้ว (ข้อ 2f) · วัด PageSpeed Insights ซ้ำอีกครั้งหลังทีม content อัปโหลดวิดีโอที่บีบอัดแล้ว — ดูแท็บ งานที่ไม่ใช่ Dev )
หลัง deploy ≥ 7 วัน (ตั้งแต่ 2 พ.ย.): ลบ route handler /api/home-setting, /api/hero-banner, /api/general-nav, /api/instagram (ไม่ใช่ /api/instagram/media) และ GET /api/contact
5) งานของ content, marketing, โรงแรม, infra, ดีไซน์ และกฎหมาย
6) ความเสี่ยงที่พบนอก audit (ไม่อยู่ใน PDF · ยังไม่แก้)
API สาธารณะเปิดเผยชื่อคนแก้ข้อมูลใน CMS (createdByName/updatedByName ในทุก /v1/public/*) — เว็บไม่ส่งต่อแล้ว แต่ต้องแก้ที่ yanh-api
ปุ่ม Book Now บนการ์ดห้องกดไม่ได้บนมือถือและด้วยคีย์บอร์ด (จะแก้พร้อมเรื่องลิงก์จอง)
ที่เป็นงาน infra และ marketing (รูป prod อยู่ใน bucket ของ dev, โดเมนเปล่า yanhhotel.com เข้าไม่ได้, GA4 ของ UAT และ PDPA) อยู่ในแท็บ งานที่ไม่ใช่ Dev
รายละเอียดเชิงเทคนิคทั้งหมดอยู่ใน SEO-AUDIT-REMEDIATION.md ที่ root ของ repo
00b · อัปเดต 26 ตุลาคม 2026
เทียบกับ PDF ทีละข้อ
แถวในรายงาน PDF ที่มีงานฝั่ง dev (ยกเว้นแผนปฏิบัติการ ซึ่งมีสถานะอยู่ในหัวข้อ 8) พร้อมสถานะปัจจุบัน "ขึ้น prod แล้ว" หมายถึง deploy prod แล้ว 26 ต.ค. และทดสอบบน prod แล้ว (ข้อ 2f) · "รอ backfill" หมายถึงโค้ดขึ้นแล้วแต่ข้อมูล SEO เดิมยังไม่ถูกย้ายไปแถวภาษา · อีก 18 ข้อที่เป็นงาน content, marketing, โรงแรม/GM หรือกฎหมายล้วนๆ อยู่ในแท็บ งานที่ไม่ใช่ Dev (รวม 79 ข้อ)
ขึ้น prod แล้ว: 32
ขึ้น prod แล้ว · รอ backfill: 2
บางส่วน: 16
ยังไม่เริ่ม: 11
รวม 61 ข้อ (+18 ข้อในแท็บงานที่ไม่ใช่ Dev)
Technical SEO (T1–T10)
ข้อใน PDF สถานะ หมายเหตุ
T1 หน้า TH/ZH canonical ไป EN ขึ้น prod แล้ว ทุกหน้า self-canonical ในภาษาของตัวเอง og:url ตาม (ตัดสินใจ 21 ต.ค.)
T2 robots.txt ชี้ sitemap ของ staging ขึ้น prod แล้ว ชี้ https://www.yanhhotel.com/sitemap.xml
T3 UAT เปิดสาธารณะ/ถูก index บางส่วน noindex ทุกโดเมนที่ไม่ใช่ www.yanhhotel.com (ขึ้น prod แล้ว — www ไม่มี header, www-prod-gcp มี) · ลบ URL ใน Search Console = marketing · IAP/รหัสผ่าน = infra
T4 canonical ชี้หน้า 404 (6 URL) ขึ้น prod แล้ว หายพร้อม T1
T5 ลิงก์ภายในไม่มีภาษานำหน้า ขึ้น prod แล้ว LocaleLink ทุกจุด + ESLint กันหลุด
T6 lastmod ใน sitemap เป็นวันนี้เสมอ ขึ้น prod แล้ว #17 ใช้วันที่แก้ไขจริงจาก CMS (ตัวหลัก + แถวภาษาของหน้า, หน้ารวมนับรายการที่แสดงด้วย) · ไม่มีวันที่ = ไม่ใส่ lastmod แทนการใส่วันนี้
T7 slug ตัวพิมพ์ใหญ่/เล็กปน บางส่วน ชั่วคราว (26 ต.ค.): URL ที่พิมพ์ตัวพิมพ์ต่างกัน เช่น /food-and-drink/tanh พาไปหน้าเดิม (redirect 307) แทน 404 · ย้ายจริงไป /dining/tanh, /meetings/tanh-2nd-floor พร้อม 301 ทำพร้อม #12 ตามที่ PDF จัดไว้
T8 path แม่ /food-and-drink, /meeting-room-and-event 404 ยังไม่เริ่ม P2 #12 (hub)
T9 path ที่ไม่รู้จักถูก redirect ไปหน้าแรก ขึ้น prod แล้ว /llms.txt, /cn, /sitemap_index.xml, /de ได้ 404 · ภาษาของเว็บเอง (en/th/zh) ที่ถูกปิดใน CMS ยัง redirect ไปภาษา default
T10 โหลด Google tag 2 ตัว บางส่วน ตรวจแล้วไม่ใช่การนับซ้ำ (GTM โหลด gtag.js ตามปกติ) · แก้ CSP ที่บล็อก hit GA4 + เพิ่ม event booking_click แล้ว · cross-domain ใน GA4/SiteMinder = งาน marketing
การ render และความเร็ว
ข้อใน PDF สถานะ หมายเหตุ
เนื้อหาหน้าแรกโหลดฝั่ง client (~56 คำใน HTML) ขึ้น prod แล้ว HTML จาก server มี 443 คำ
เมนูหลักและที่อยู่ footer โหลดฝั่ง client · "Copyright undefined" ขึ้น prod แล้ว server-render ทั้งเมนู desktop และ footer
Performance: LCP 7.9 วิ, CLS 0.705, หน้า 5.7 MB, render-blocking, cache สั้น, JS ไม่ได้ใช้ บางส่วน #15 ขึ้น prod แล้ว (ดูหัวข้อ 0 ข้อ 2b, 2f): บน prod หลัง deploy CLS 0 (เดิม 0.80), LCP มือถือ 6.86 วิ (เดิม 9.4–10), หน้า 1.73 MB (เดิม 2.52) · เหลือ: อัปโหลดวิดีโอ (content), cache ไฟล์เก่าใน bucket (infra), CSS ที่บล็อก render ~0.3 วิ
ปุ่มไม่มี accessible name, contrast ต่ำ บางส่วน ปุ่มไอคอนมีชื่อครบแล้ว (Lighthouse accessibility 89 → 95–96) · contrast เป็นสีแบรนด์ ต้องให้ดีไซน์อนุมัติสีใหม่
Metadata
ข้อใน PDF สถานะ หมายเหตุ
title ไม่มี "Bangkok"/"hotel" บางส่วน suffix ตาม PDF ทุกภาษา (เช่น Rooms | YANH Ratchawat Hotel, Bangkok) · หลัง backfill title หน้าแรกจะกลับเป็นค่าใน CMS "YANH Ratchawat" (ไม่มี Bangkok) รอ content แก้
title คำเดียว / description ซ้ำ title ขึ้น prod แล้ว มี suffix และ description ใช้เนื้อหาจริงแทน
tag ผิดภาษา (title ไทยบนหน้า EN ฯลฯ) ขึ้น prod แล้ว · รอ backfill SEO แยกตามภาษา (Option A) ทั้ง 3 repo · ย้ายค่าเดิมตามอักษรที่เขียน
ใช้ tagline แทนชื่อร้าน (Groundwork, TANH) ขึ้น prod แล้ว ใช้ displayName
ห้องประชุมไม่มีชื่อห้อง/ความจุใน title ขึ้น prod แล้ว เช่น Unwind Room – TANH, 3rd Floor (18 seats)
อักขระซ่อน U+200B ขึ้น prod แล้ว ตัดออกจาก title/H1/JSON-LD
ความยาว title/description บางส่วน fallback ตัดที่ 60/145 · CMS เตือนแบบ Bridge · ค่าที่ยาวเกินใน CMS = content
brand suffix ไม่สม่ำเสมอ ขึ้น prod แล้ว กติกาเดียวทุกหน้า (title ที่มีแบรนด์แล้ว เช่น "Contact | YANH Hotel" คงไว้จน content แก้)
ไม่มี og:image 75/81 URL ขึ้น prod แล้ว #16 ทุกหน้ามีรูป: รูป SEO จาก CMS ก่อน ถ้าว่างใช้รูป header/รูปของห้อง venue บทความนั้น · หน้า PDPA ที่ไม่มีรูปใช้รูป SEO ของหน้าแรก
H1 หาย/ซ้ำ/ผิด (หน้าแรก, F&B, ห้องประชุม, Cookies) ขึ้น prod แล้ว H1 เดียวต่อหน้า
title ไทย (แบรนด์ไทย + เขต) และจีน (曼谷 + 酒店) บางส่วน suffix ไทย/จีนตาม PDF แล้ว · ข้อความโดยเจ้าของภาษา = content
Structured data และ entity
ข้อใน PDF สถานะ หมายเหตุ
Hotel + WebSite ในทุกหน้า บางส่วน ทำแล้ว · พิกัด, จำนวนห้อง, check-in/out, amenities รอโรงแรมยืนยัน
HotelRoom (6 หน้าห้อง) ขึ้น prod แล้ว —
Restaurant (TANH) / CafeOrCoffeeShop (Groundwork) ขึ้น prod แล้ว เวลาเปิดอ่านจากข้อความ "Open daily" ภาษาอังกฤษ · servesCuisine เว้นไว้ เพราะ CMS ไม่มีข้อมูลประเภทอาหาร
MeetingRoom (4 หน้า) ขึ้น prod แล้ว ความจุ 8/10/20/18 และพื้นที่ 23/28/95/90 ตร.ม. ตรงกับ PDF · amenityFeature จากรายการอุปกรณ์ในหน้า
Article (บทความย่าน, blog) ขึ้น prod แล้ว headline, datePublished, dateModified, author/publisher = โรงแรม, image · บทความย่านมี about → Place (ที่อยู่ + แผนที่จาก CMS) · blog ไม่มีข้อมูลสถานที่จึงไม่มี about
BreadcrumbList (หน้าภายใน) ขึ้น prod แล้ว —
FAQPage ยังไม่เริ่ม ต้องมีหน้า FAQ ก่อน (P2 #13)
ที่อยู่ไม่อยู่ใน server HTML และหน้า Contact ขึ้น prod แล้ว footer + หน้า Contact (บั๊ก translation/translations)
ตรวจด้วย Rich Results Test / Schema validator ยังไม่เริ่ม deploy แล้ว ทำได้เลย · JSON-LD parse ผ่าน 159/159 บน prod แต่ยังไม่ได้รันเครื่องมือของ Google · Restaurant/Cafe จะถูกฟ้องเรื่อง address (บั๊ก low ข้อ 2d)
AEO / การมองเห็นบน AI
ข้อใน PDF สถานะ หมายเหตุ
2. server-render หน้าแรกและเมนู ขึ้น prod แล้ว —
3. หน้า FAQ (EN/TH/ZH) ยังไม่เริ่ม P2 #13
4. หน้า Location & Getting Here ยังไม่เริ่ม P2 #13
5. หน้า Press + เครดิต CHAT Architects ยังไม่เริ่ม P2 #20
6. แสดงคะแนนรีวิวแขก ยังไม่เริ่ม P2 #20
llms.txt (ไม่บังคับ) ยังไม่เริ่ม ความสำคัญต่ำ
Content
ข้อใน PDF สถานะ หมายเหตุ
หน้าแรก: H1 ขึ้น prod แล้ว H1 แบบซ่อน (ตั้งค่าผ่าน Language Variable web.home.heading)
Offers: title EN เป็นภาษาไทย ขึ้น prod แล้ว · รอ backfill ค่าภาษาไทยย้ายไปแถว TH · หน้า EN ใช้ "Special Offers" + suffix
Offers: โชว์ข้อเสนอหลักบนหน้าแรก/หน้าห้อง ยังไม่เริ่ม —
Blog: ย้ายฟอร์มสื่อไป /press ขึ้น prod แล้ว #23 หน้าอยู่ที่ /press · URL เดิม 301 ไป /press
H1 Cookies Policy / Terms ขึ้น prod แล้ว —
"Copyright undefined" ขึ้น prod แล้ว —
alt text ทั่วไป ("Our Story Image 01", "WELCOME TO") ขึ้น prod แล้ว ไล่ครบทุก alt ในโค้ด (26 ต.ค.): รูปพื้นหลัง/ตกแต่ง และไอคอนที่มีชื่อเขียนอยู่ข้างๆ → alt ว่าง · รูปจริงใช้ชื่อห้อง ร้าน facility หรือบทความ · ปุ่มที่มีแต่รูป (gallery, แชร์) มีชื่อเสมอ · ตัด HTML ที่ติดมาจากชื่อใน CMS · ตรวจ 18 หน้าแล้วไม่เหลือ alt กว้างๆ และไม่มีรูปที่ขาด alt
caption Instagram ตัวหนาแบบ Unicode บางส่วน บนเว็บแปลงเป็นตัวปกติใน alt แล้ว · caption บน Instagram เอง = งาน content
Structure และ UX
ข้อใน PDF สถานะ หมายเหตุ
หน้าสร้างรายได้ไม่มีลิงก์เข้า (orphan) บางส่วน วิธีตาม PDF (Dining/Meetings hub ในเมนูหลัก + ลิงก์ tile ใน Facilities = #12) ยังไม่ทำ · แนวทางชั่วคราวของผู้แก้ · ไม่อยู่ใน PDF ใส่ลิงก์ 6 หน้าใน footer ให้ crawler เข้าถึงได้แล้ว (รอตัดสินใจ ข้อ 3)
เมนูหลัก บางส่วน server-render แล้ว · ยังเป็น 5 รายการ ไม่ใช่โครงสร้าง 8 ส่วน
ลิงก์จอง: วันที่ผ่านแล้ว, locale=en ขึ้น prod แล้ว วันนี้→พรุ่งนี้ (เวลาไทย), th / zh-CN, THB
date picker ใน header ยังไม่เริ่ม เลื่อนไปทำทีหลัง (ตามที่ตกลง)
Attribution / GA4 cross-domain บางส่วน event booking_click + แก้ CSP แล้ว · ตั้งค่า GA4/SiteMinder = งาน marketing
ภาษารั่ว (ลิงก์ไม่มีภาษา) ขึ้น prod แล้ว —
ฟอร์มสื่ออยู่ใต้ /blog/ ขึ้น prod แล้ว #23 ย้ายไป /press พร้อม 301 · เมนูยังอยู่ใต้ Blog (ย้ายไปใต้ Our Story ตามแผนภาพ PDF รวมกับงานเมนู 8 ส่วน)
slug ตัวพิมพ์เล็ก + 301 บางส่วน ดู T7 — ลิงก์ตัวเล็กไม่ 404 แล้ว · ย้าย URL จริงรอ #12
หน้า Contact: ที่อยู่, แผนที่, ปุ่ม LINE/โทร บางส่วน ที่อยู่กลับมาแล้ว (แผนที่มีอยู่) · ปุ่ม LINE/โทรเด่นๆ ยังไม่ทำ
น้ำหนักหน้าแรก (Instagram 26 โพสต์) ขึ้น prod แล้ว 6 โพสต์ · รูปย่อ ~30 KB · โหลดเมื่อเลื่อนถึง
Footer (ที่อยู่, เบอร์, LINE, หน้าหลัก) ขึ้น prod แล้ว ที่อยู่ เบอร์ ลิงก์หน้าอื่น อยู่ใน HTML จาก server · LINE เป็นไอคอนเดิม · รายการลิงก์ที่ใส่เป็นแนวทางของผู้แก้ (รอตัดสินใจ ข้อ 3)
Accessibility บางส่วน alt="t", <a> ซ้อน <button>, label ปุ่มไอคอน (ปิด cookie, ตั้งค่า cookie, VR), alt ทุกจุด แก้แล้ว · contrast รอดีไซน์
โครงสร้างเว็บใหม่ 8 ส่วน + hub 3 หน้า ยังไม่เริ่ม P2/P3
ข้อมูลที่ต้องได้จากโรงแรม (PDF หน้า 15) ทั้ง 4 ข้อเป็นงานของโรงแรม — อยู่ในแท็บ
งานที่ไม่ใช่ Dev
01
สรุปสำหรับผู้บริหาร (Executive summary)
yanhhotel.com ดูดี แต่ยังไม่ได้ทำหน้าที่เชิงพาณิชย์ของมัน ข้อผิดพลาดในการตั้งค่าทำให้ Google มองไม่เห็นเว็บภาษาไทยและภาษาจีน และเปิดสำเนาเว็บ staging ให้สาธารณะเข้าถึงได้ เนื้อหาหน้าแรก เมนู และที่อยู่ ไม่ปรากฏต่อ AI crawler และเมื่อค้นหาด้วยชื่อแบรนด์ ผลที่ได้คือ OTA และเว็บจองลอกเลียนแบบที่ไม่เป็นทางการ แทนที่จะเป็นเว็บของโรงแรมเอง งานแก้ระดับ P1 ใช้เวลาประมาณ 6 วันทำงานของนักพัฒนา
38/54
หน้า TH/ZH ที่ตั้ง canonical ไปหน้า EN
0/27
title EN ที่มีคำว่า "Bangkok"
75/81
URL ที่ไม่มีรูปสำหรับแชร์ (og:image)
0/4
คำค้นชื่อแบรนด์ที่เว็บทางการติดผล
7.9 วิ
LCP บน mobile (เกณฑ์ ≤ 2.5 วิ)
Technical SEO อ่อน · Weak
หน้า TH/ZH 38 จาก 54 หน้าตั้ง canonical ไปที่หน้าภาษาอังกฤษ · robots.txt ประกาศ sitemap ของ staging · เว็บ staging เปิดสาธารณะและถูก index ได้
Metadata อ่อน · Weak
title ภาษาอังกฤษ 0 จาก 27 หน้ามีคำว่า "Bangkok" · มี title ภาษาไทยอยู่บนหน้าภาษาอังกฤษ · 75 จาก 81 URL ไม่มีรูปสำหรับแชร์
Structured data & entity อ่อน · Weak
ไม่มี schema บนหน้าใดเลย · ไม่มีที่อยู่ทั้งใน server HTML และในหน้า Contact
AEO / การมองเห็นบน AI อ่อน · Weak
เว็บทางการไม่ปรากฏเลยในการค้นหาชื่อแบรนด์ทั้ง 4 ครั้งที่ทดสอบ · เว็บจองลอกเลียนแบบที่ไม่เป็นทางการขึ้นมาแทน
Content พอใช้ · Fair
เรื่องราวของอาคารและย่านแข็งแรง · หน้า meetings และ dining มีเนื้อหาน้อย · มีบทความ blog เพียง 1 บทความตั้งแต่ปี 2023
Structure & UX อ่อน · Weak
หน้า dining และ meeting เป็นหน้า orphan (ไม่มีลิงก์ใดชี้เข้า) · ลิงก์จองห้องพักเปิดด้วยวันที่ที่ผ่านไปแล้ว
Speed พอใช้ · Fair
คะแนน mobile 64, LCP 7.9 วินาที · layout shift บน desktop 0.705
ควรแก้ก่อน และเหตุผลที่ทำให้เสียเงินอยู่ทุกวันนี้
หน้าภาษาไทยและจีนตั้ง canonical ไปที่ภาษาอังกฤษ (T1) — แขกชาวไทย ซึ่งเป็นกลุ่มที่อยู่เบื้องหลังข่าวสื่อไทยเกี่ยวกับ YANH และโพสต์ staycation บน Lemon8 หาหน้าภาษาไทยไม่เจอ จึงไปจองผ่าน OTA
เว็บ staging และ sitemap ของ staging เปิดสาธารณะ (T2, T3) — เว็บซ้ำอีกชุดหนึ่งแย่งผลการค้นหาชื่อแบรนด์กับเว็บ production
หน้าแรก เมนู และที่อยู่ render ฝั่ง client และไม่มี schema — ผู้ช่วย AI ไม่สามารถอธิบายหรือแนะนำโรงแรมจากเว็บของโรงแรมเองได้
หน้า dining และ meeting ไม่มีลิงก์เข้า และปุ่มจองแนบวันที่ที่ผ่านไปแล้ว — รายได้ที่ไม่ใช่ห้องพักจึงมองไม่เห็น และ conversion ของการจองตรงรั่วไหลตรงคลิกสุดท้าย
ยังไม่ได้วัดผลกระทบเป็นตัวเลข เนื่องจากไม่มีสิทธิ์เข้าถึง Search Console หรือ GA4 งานแรกคือ export ข้อมูล Search Console ย้อนหลัง 16 เดือน เพื่อตั้ง baseline ของจำนวนคลิกจากชื่อแบรนด์, impressions ของหน้า TH/ZH และ conversion ของการจองตรง
ขอบเขตการตรวจ: URL ทั้ง 81 รายการใน sitemap (EN, TH, ZH) ถูก crawl ทั้งแบบ raw server HTML และแบบหน้าที่ render แล้ว, robots.txt, sitemaps, staging host, PageSpeed Insights (หน้าแรก ทั้ง mobile และ desktop), การค้นหาชื่อแบรนด์ 4 คำค้น และการตรวจเทียบกับรายการบน OTA และข่าวในสื่อ
02
Technical SEO และการ crawl
ตัว build เองไม่มีปัญหา — เป็น Next.js แบบ server-rendered, ใช้ HTTPS, มี hreflang ทุกหน้า, มีหน้า 404 จริง — แต่มี ข้อผิดพลาดในการตั้งค่า 3 จุด ที่บอกให้ Google เพิกเฉยต่อเว็บภาษาไทยและจีน แล้วชี้ไปที่สำเนา staging ที่เปิดสาธารณะแทน ทั้ง 3 จุดเป็นงานแก้ของนักพัฒนาที่วัดเป็นชั่วโมง ไม่ใช่สัปดาห์
ขอบเขตการ crawl: URL ทั้ง 81 รายการใน XML sitemap (27 หน้า × EN/TH/ZH) ดึงเป็น raw server HTML เมื่อวันที่ 5 ตุลาคม 2026 รวมถึงการตรวจ redirect, 404 และ staging
# ปัญหาที่พบ หลักฐาน ทำไมจึงสำคัญ วิธีแก้ Priority
T1 หน้าภาษาไทยและจีนตั้ง canonical ไปที่ภาษาอังกฤษ URL ของ TH/ZH 38 จาก 54 รายการมี rel=canonical ชี้ไปที่ URL ภาษาอังกฤษ — รวมถึง /th, /zh, Rooms, Facilities, Our Story, Contact, Offers, F&B และ Meetings มีเพียงหน้าห้องพัก 6 หน้า, บทความ blog 1 บทความ และหน้า Cookies ที่ self-canonical ส่วน og:url ก็ผิดแบบเดียวกัน canonical มีผลเหนือกว่า hreflang Google จะถือว่าหน้า TH/ZH เป็นหน้าซ้ำของภาษาอังกฤษ และส่วนใหญ่จะไม่ index — ตลาดคนไทยในประเทศและนักท่องเที่ยวจีนจึงไปลงที่หน้าภาษาอังกฤษหรือ OTA ทุกหน้าต้อง self-canonical ในภาษาของตัวเอง คง hreflang ไว้ตามเดิม P1
T2 robots.txt ประกาศ sitemap ของ staging Sitemap: https://www-uat.yanhhotel.com/sitemap.xmlGoogle ถูกสั่งให้ crawl URL ของ staging host แทนที่จะเป็นของ production ชี้ไปที่ https://www.yanhhotel.com/sitemap.xml P1
T3 เว็บ staging เปิดสาธารณะและถูก index ได้ www-uat.yanhhotel.com ให้บริการเว็บครบทั้งเว็บ, robots.txt เป็น Allow: /, self-canonical ไปที่ www-uat, ไม่มี noindex สำเนาเว็บโรงแรมที่สมบูรณ์อีกชุดหนึ่งแข่งกับ production ในผลการค้นหาชื่อแบรนด์ ตั้งรหัสผ่านป้องกัน UAT (หรือใส่ X-Robots-Tag: noindex + robots Disallow) แล้วลบ URL ของ UAT ที่ถูก index ไปแล้วผ่าน Search Console P1
T4 canonical ชี้ไปที่หน้า 404 /en/blog → /en/blog-and-review (404); /blog/media-and-influencer-request → /en/media-influencer-request (404) บน TH/ZH ก็เป็นแบบเดียวกัน รวม 6 URL canonical ที่ชี้ไป URL ที่ตายแล้ว อย่างดีที่สุดคือถูกเพิกเฉย อย่างแย่ที่สุดคือทั้งสอง URL หลุดจาก index ทำ self-canonical P1
T5 ลิงก์ภายในไม่มี prefix ภาษา ลิงก์ในเนื้อหาและ footer ใช้ /our-story, /rooms/…, /facilities, /privacy-policy ซึ่ง redirect ไปที่ /en/… บนหน้า TH และ ZH ลิงก์ชุดเดียวกันนี้จึงส่ง crawler (และผู้ใช้ที่ไม่มี cookie) ไปหน้าภาษาอังกฤษ การ์ดห้องพักและลิงก์ "Learn more" ทุกอันบนเว็บไทยพาผู้ใช้ออกจากเว็บไทย และ link equity ต้องไหลผ่าน redirect เพิ่มอีก 1 hop สร้าง href ทุกตัวพร้อม locale ปัจจุบัน (/th/rooms/…) P1
T6 lastmod ใน sitemap เป็นวันนี้เสมอsitemap ของ static, rooms, F&B และ meetings ประทับวันที่ 2026-10-05 ให้ทุก URL (สร้างขึ้นตอนมี request) ส่วน Blog = 2023-03-01, neighbourhoods = 2024 Google จะเรียนรู้ว่าวันที่นี้ไม่มีความหมาย และเลิกใช้ในการจัดตารางการ crawl ซ้ำ ส่งวันที่แก้ไขเนื้อหาจริงจาก CMS P2
T7 slug ตัวพิมพ์ใหญ่-เล็กปนกัน และแยกตัวพิมพ์ (case-sensitive) /food-and-drink/TANH, /meeting-room-and-event/TANH-2nd เทียบกับ /tanh-3rd-floor ส่วนตัวพิมพ์เล็ก /food-and-drink/tanh ได้ 404ลิงก์ที่พิมพ์เองหรือแชร์ต่อจะพัง และรูปแบบไม่สม่ำเสมอ เปลี่ยน slug ทั้งหมดเป็นตัวพิมพ์เล็ก (/dining/tanh, /meetings/tanh-2nd-floor) และทำ 301 จาก URL เดิม P2
T8 path ระดับแม่ได้ 404 /en/food-and-drink และ /en/meeting-room-and-event (ซึ่งเป็นแม่ของหน้าที่ใช้งานอยู่ 6 หน้า) ได้ 404 breadcrumb ระดับนั้นตาย และไม่มี hub page ไว้ติดอันดับคำค้น "restaurant" หรือ "meeting room" สร้าง hub page 2 หน้า (ดูหัวข้อ Structure) P2
T9 path ที่ไม่รู้จักระดับ root ถูก redirect ไปหน้าแรก /llms.txt, /cn, /sitemap_index.xml → ได้ 200 ที่ /en ส่วน path ภายใต้ /en/ คืน 404 ถูกต้อง เป็นรูปแบบ soft-404 ปัญหาเล็กน้อย คืน 404 สำหรับ path ระดับ root ที่ไม่รู้จัก P3
T10 โหลด Google tag สองตัว ทั้ง gtag.js และ gtm.js ทำงานตอนโหลดหน้า ส่วน booking engine อยู่บน book-directonline.com เสี่ยงนับ session ซ้ำ และ attribution ของการจองตรงผิดพลาด รวมไว้ใน GTM ที่เดียว และยืนยันการตั้งค่า GA4 cross-domain linking ไปยัง booking engine P2
ส่วนที่ทำงานถูกต้องแล้ว: HTTPS · URL ที่มี trailing slash และ ?utm_ ตั้ง canonical ไปที่ URL ที่สะอาด · มี hreflang (en, th, zh, x-default) ครบทั้ง 81 หน้า · ตั้งค่า HTML lang ตาม locale · รูปบนหน้าแรก 65 จาก 66 รูปเป็น lazy-load · มี template 404 จริงภายใต้ /en/
การ render และความเร็ว
เนื้อหาบนหน้าแรก ทั้งเรื่องราว, ส่วนแนะนำห้องพัก, ย่าน และ "Experience YANH" ถูก fetch ในเบราว์เซอร์ ไม่ได้ส่งมาใน HTML — response จาก server มีข้อความเนื้อหาราว 56 คำ เมนูหลักและที่อยู่ใน footer ก็ render ฝั่ง client เช่นกัน (footer ใน raw HTML เขียนว่า "Copyright undefined") Google render JavaScript ได้ แต่ AI crawler ส่วนใหญ่ไม่ render จึงเห็นหน้าแรกที่แทบว่างเปล่าและไม่มีเมนู ส่วนหน้าภายใน (Our Story, Rooms, หน้าห้องพัก) render ฝั่ง server ได้ถูกต้อง
PageSpeed Insights หน้าแรก วันที่ 5 ตุลาคม 2026 (lab data — Chrome UX Report ไม่มี field data ของเว็บนี้ เพราะ traffic น้อยเกินกว่าจะเข้าเกณฑ์):
ตัวชี้วัด Mobile Desktop เกณฑ์ที่ดี
Performance score 64 45 ≥ 90
Largest Contentful Paint (LCP) 7.9 วิ 0.6 วิ ≤ 2.5 วิ
First Contentful Paint (FCP) 3.5 วิ 0.3 วิ ≤ 1.8 วิ
Total Blocking Time (TBT) 130 ms 700 ms ≤ 200 ms
Cumulative Layout Shift (CLS) 0 0.705 ≤ 0.1
Accessibility / Best practices / SEO (mobile) 89 / 92 / 92 — ≥ 90
สาเหตุหลักที่ถูกชี้: หน้าเว็บหนัก 5.7 MB, request ที่บล็อกการ render (ประมาณ 1.5 วินาที), asset 4.3 MB ที่ตั้ง cache lifetime สั้น, JavaScript ที่ไม่ได้ใช้ 191 KB, ปุ่มที่ไม่มี accessible name และข้อความที่ contrast ต่ำ ค่า layout shift บน desktop 0.705 หมายความว่าเนื้อหากระโดดขณะที่ hero และ feed โหลด — ให้กำหนดขนาดรูปไว้ล่วงหน้า และโหลด Instagram feed ที่อยู่ใต้ fold เฉพาะเมื่อผู้ใช้เลื่อนลงมาถึง
04
Structured data และ entity
ไม่มี structured data เลย: JSON-LD 0 บล็อกจากทั้ง 81 URL สำหรับโรงแรม นี่คืองานแก้ที่ถูกที่สุดแต่ได้ผลสูง เพราะเป็นการส่งชื่อ ที่อยู่ ห้องพัก สิ่งอำนวยความสะดวก และ venue ให้ Knowledge Graph ของ Google และ AI answer engine ในรูปแบบที่ไม่ต้องเดา
ที่อยู่ก็หายไปจากจุดที่เครื่องมองหา — ปรากฏเฉพาะใน footer ที่ render ฝั่ง client ("1376/1 Nakornchaisri Road, Dusit, Bangkok 10300") footer ใน server HTML ไม่มีที่อยู่ หน้า Contact มีเบอร์โทรและอีเมลแต่ไม่มีที่อยู่หรือแผนที่ และ OTA สะกดชื่อถนนต่างกัน (Trip.com: "1376/1 Nakhonchaisi Rd")
Schema ที่ต้องเพิ่ม แยกตาม template
Template Type property หลัก
ทุกหน้า (ใส่ใน layout) Hotel (มี @id เดียว อ้างอิงจากทุกที่) + WebSite name, alternateName, address, geo, telephone, email, numberOfRooms, checkinTime, checkoutTime, amenityFeature, sameAs, image
หน้าห้องพัก 6 หน้า HotelRoom, containedInPlace → Hotel name, floorSize, occupancy, bed, amenityFeature, image
TANH Restaurant servesCuisine, openingHoursSpecification, containedInPlace
Groundwork CafeOrCoffeeShop openingHoursSpecification, containedInPlace
หน้า meeting 4 หน้า MeetingRoom maximumAttendeeCapacity (8, 10, 20, 18), floorSize (23, 28, 95, 90 m²), amenityFeature
บทความย่าน, blog Article ที่มี about → Place headline, datePublished, dateModified, author, image
หน้าภายในทุกหน้า BreadcrumbList —
หน้า FAQ ใหม่ FAQPage Google แสดง FAQ rich results ให้เฉพาะเว็บที่มี authority สูงไม่กี่เว็บ แต่ markup นี้ยังให้คู่คำถาม–คำตอบที่สะอาดแก่ AI engine
Hotel entity พร้อมวาง (EN — ทำซ้ำสำหรับแต่ละ locale โดยแปลชื่อและคำอธิบาย)
ค่าที่อยู่ในวงเล็บมุม < > (ไฮไลต์สีแดง) ต้องให้โรงแรมยืนยันก่อน release ส่วนค่าอื่นทั้งหมดนำมาจากเว็บไซต์จริงหรือรายการบน OTA ของโรงแรม (78 ห้อง)
{
"@context": "https://schema.org",
"@type": "Hotel",
"@id": "https://www.yanhhotel.com/#hotel",
"name": "YANH Ratchawat Hotel",
"alternateName": ["YANH Ratchawat", "โรงแรมย่าน ราชวัตร"],
"description": "A 78-room neighbourhood hotel in a restored 1980s tech building in Ratchawat, Dusit, Bangkok.",
"url": "https://www.yanhhotel.com/en",
"telephone": "+66 2 180 6450",
"email": "[email protected] ",
"address": {
"@type": "PostalAddress",
"streetAddress": "1376/1 <Nakhon Chai Si Road — match Google Business Profile spelling> ",
"addressLocality": "Dusit",
"addressRegion": "Bangkok",
"postalCode": "10300",
"addressCountry": "TH"
},
"geo": { "@type": "GeoCoordinates", "latitude": "<from GBP pin> ", "longitude": "<from GBP pin> " },
"numberOfRooms": 78,
"checkinTime": "<14:00?> ",
"checkoutTime": "<12:00?> ",
"amenityFeature": [
{ "@type": "LocationFeatureSpecification", "name": "Outdoor swimming pool", "value": true },
{ "@type": "LocationFeatureSpecification", "name": "Fitness room", "value": true },
{ "@type": "LocationFeatureSpecification", "name": "Free Wi-Fi", "value": true },
{ "@type": "LocationFeatureSpecification", "name": "Car parking", "value": true },
{ "@type": "LocationFeatureSpecification", "name": "Meeting rooms", "value": true },
{ "@type": "LocationFeatureSpecification", "name": "24-hour front desk", "value": true },
{ "@type": "LocationFeatureSpecification", "name": "Massage service", "value": true },
{ "@type": "LocationFeatureSpecification", "name": "Non-smoking rooms", "value": true }
],
"sameAs": [
"https://www.facebook.com/yanhratchawat",
"https://www.instagram.com/yanhratchawat"
],
"image": "<absolute URL of the hero image> "
}
ความหมายของ placeholder: <Nakhon Chai Si Road — match Google Business Profile spelling> = สะกดชื่อถนนให้ตรงกับ Google Business Profile · <from GBP pin> = พิกัดจากหมุดใน Google Business Profile · <14:00?> / <12:00?> = เวลา check-in / check-out ที่ต้องยืนยัน · <absolute URL of the hero image> = URL เต็มของรูป hero
เมื่อขึ้นระบบแล้ว ให้ตรวจสอบด้วย Rich Results Test ของ Google และ Schema.org validator และทำให้ชื่อ ที่อยู่ และเบอร์โทร (NAP) ปรากฏเหมือนกันทุกตัวอักษรใน footer (render ฝั่ง server), หน้า Contact, Google Business Profile และ extranet ของ OTA ทุกเจ้า
05
AEO / การมองเห็นบน AI
Answer engine มีวัตถุดิบที่ดีเกี่ยวกับ YANH อยู่แล้ว — สื่อไทยและสื่อสายดีไซน์เล่าเรื่องไว้ดี — แต่ไม่มีอะไรชี้พวกมันมาที่ yanhhotel.com ในการค้นหาชื่อแบรนด์ 4 ครั้ง เว็บทางการไม่ปรากฏในผลอันดับต้นเลยสักครั้ง แต่เว็บจองลอกเลียนแบบที่ไม่เป็นทางการกลับปรากฏ
คำค้น (5 ต.ค. 2026) ผลที่ได้ มีเว็บทางการในผลหรือไม่
YANH Ratchawat Booking.com, art4d, trivago, Facebook, Wanderlog, Trip.com, บล็อกท่องเที่ยว 1 เว็บ, เว็บ clone 2 เว็บ ไม่มี (top 9)
YANH Ratchawat hotel Bangkok address Google Hotels entity, Traveloka, Trip.com ×2, Prestigia, VenueReport, เว็บ affiliate clone 4 เว็บ (bangkokshotels, bangkokhotel24, bangkoktophotels, bangkokihotel) ไม่มี (top 10)
โรงแรม YANH ราชวัตร The Standard, BKKMENU, Lemon8 ×2, Trip.com TH, Pratuneung, Readthecloud และเว็บ clone ที่ติดป้ายว่า "เว็บไซต์" ไม่มี (top 9)
"yanhhotel.com" Instagram, BKKMENU, Trip.com, Readthecloud ไม่พบ ตัวโดเมนเองในผลลัพธ์
วิธีการ: ใช้ดัชนีการค้นหาเว็บของ Claude ไม่ใช่ Google ให้ถือเป็นสัญญาณเบื้องต้น แล้วยืนยันใน Search Console (อันดับของคำค้นชื่อแบรนด์) และด้วยการถาม ChatGPT, Perplexity, Gemini และ Google AI Mode ว่า "What is the official website of YANH Ratchawat?" (เว็บไซต์ทางการของ YANH Ratchawat คืออะไร)
เว็บ clone มีผลเชิงพาณิชย์: yanhratchawat.com-bangkok.com ระบุใน footer ของตัวเองว่า "not an official website" (ไม่ใช่เว็บไซต์ทางการ) แต่รับจองห้อง และโฆษณาราคา "up to 10% less than Booking.com" (ถูกกว่า Booking.com สูงสุด 10%) ผู้ช่วย AI ที่ถูกถามหา "เว็บไซต์ของโรงแรม" อาจส่งแขกไปที่เว็บนี้ — ทำให้เสียค่าคอมมิชชัน และไม่ได้ข้อมูลแขก
สิ่งที่ engine รู้อยู่แล้ว เทียบกับสิ่งที่เว็บบอก
ข้อเท็จจริง ในสื่อ บน yanhhotel.com
YANH = "Your Average Neighborhood Hotel"; ย่าน = neighbourhood art4d มี Our Story
อาคารของบริษัทคอมพิวเตอร์ยุคต้นทศวรรษ 1980 ผนังกระเบื้องสี่เหลี่ยมสีขาว art4d มี Our Story และหน้าแรก (แต่เนื้อหาหน้าแรก render ฝั่ง client)
สถาปนิก: CHAT Architects; ผู้พัฒนาโครงการ: SC Asset art4d ไม่มี
ที่อยู่, เขต, วิธีเดินทาง OTA มีเฉพาะใน footer ที่ render ฝั่ง client · ไม่มีแผนที่ ไม่มีเส้นทาง
คะแนนรีวิว (Trip.com 9.2/10 จาก 297 รีวิว) OTA ไม่มี คะแนนรีวิวหรือคำพูดจากแขก
เวลา check-in/out, เวลาอาหารเช้า, เงื่อนไขที่จอดรถ, สัตว์เลี้ยง, รถรับส่งสนามบิน ไม่ได้ตรวจ ไม่มี
งานแก้ เรียงตามผลกระทบ
ชี้ทุกโปรไฟล์ที่โรงแรมเป็นเจ้าของมาที่ yanhhotel.com — ช่อง website ของ Google Business Profile, ช่อง "hotel website" บน OTA, bio ของ Facebook, Instagram และ LINE — และขอให้สื่อที่กล่าวถึงข้างต้นลิงก์มาที่เว็บทางการ นี่คือวิธีที่ engine เรียนรู้ว่าโดเมนไหนคือ "ทางการ"
Server-render เนื้อหาหน้าแรกและเมนูนำทาง (ดูหัวข้อ Technical → การ render) — GPTBot, ClaudeBot และ PerplexityBot โดยทั่วไปไม่รัน JavaScript ปัจจุบัน robots.txt อนุญาต bot เหล่านี้อยู่แล้ว ให้คงไว้แบบนั้น
เผยแพร่หน้า FAQ (EN/TH/ZH, 15–20 คำตอบ, มี FAQPage markup) ครอบคลุม: ทำเลและการเดินทาง, สถานที่สำคัญใกล้เคียงพร้อมเวลาเดินที่วัดจริง, check-in/out, อาหารเช้าที่ TANH, เวลาเปิดสระและยิม, ที่จอดรถ, Wi-Fi และอุปกรณ์สำหรับทำงาน, ห้องสำหรับ 4 คน, การพักระยะยาว, ความจุและราคาห้องประชุม, สัตว์เลี้ยง, รถรับส่งสนามบิน แล้วนำคำตอบที่เกี่ยวข้อง 3–4 ข้อไปใส่ซ้ำในแต่ละหน้าห้องพักและหน้า meeting
เพิ่มหน้า Location & Getting Here ที่มีที่อยู่ภาษาอังกฤษและภาษาไทย, แผนที่แบบฝัง, การ์ดภาษาไทยสำหรับยื่นให้คนขับแท็กซี่ และสถานที่สำคัญที่แขกค้นหา (ตลาดราชวัตร, ตลาดศรีย่าน, วัดเบญจมบพิตร, บริเวณพระราชวังดุสิต)
เพิ่มหน้า Press ที่อ้างอิง art4d, The Standard, Readthecloud และ BKKMENU และให้เครดิต CHAT Architects ในหน้า Our Story — ข้อเท็จจริงที่มีหลายแหล่งยืนยันตรงกันคือสิ่งที่คำตอบของ AI จะนำมาพูดซ้ำ
แสดงคะแนนรีวิวของแขก (widget จาก OTA หรือ review aggregator) บนหน้า Home และ Rooms แต่ อย่า mark up เป็น AggregateRating บนเว็บของโรงแรมเอง เพราะ Google ถือว่าเป็นการรีวิวตัวเอง (self-serving) และจะเพิกเฉย
พิจารณาดำเนินการกับโดเมน clone (ร้องเรียนต่อ registrar หรือร้องเรียนด้านแบรนด์) หลังจากสัญญาณทางการข้างต้นพร้อมแล้ว — ต้องขอคำปรึกษาทางกฎหมาย
ไฟล์ llms.txt เป็นทางเลือกและมีความสำคัญต่ำ: ปัจจุบันยังไม่มี engine หลักรายใดพึ่งพาไฟล์นี้ และ /llms.txt ตอนนี้ redirect ไปที่หน้าแรก
06
Content (เนื้อหา)
เรื่องราวคือสินทรัพย์ — อาคารบริษัทคอมพิวเตอร์ยุค 1980, ด้านหน้าอาคารกระเบื้องสีขาว, ย่านสตรีทฟู้ด — แต่ copy ขายเรื่องนี้ด้วยประโยคสร้างอารมณ์ (mood lines) และหน้าที่สร้างรายได้นอกเหนือจากห้องพัก (meetings, dining, offers) คือหน้าที่เนื้อหาบางที่สุดและมีลิงก์เข้าน้อยที่สุด
สิ่งที่ใช้ได้ดี: Our Story (ประมาณ 450 คำ) อธิบายที่มาของชื่อและประวัติอาคารได้น่าเชื่อถือ · คู่มือย่าน (ตลาดราชวัตร, P. Look Chin Sriyan) คือเนื้อหาท้องถิ่นแบบที่ Google และ AI engine ให้คุณค่า · หน้าห้องพักมีข้อเท็จจริงที่ชัดเจน (ตร.ม., เตียง, จำนวนผู้เข้าพัก, ทีวี) · หน้า meeting ระบุความจุและขนาด
ด้าน ปัญหา วิธีแก้
หน้าแรก มีข้อความประมาณ 56 คำใน server HTML · ไม่มี H1 · H2 เขียนว่า "WELCOME TO" และ "YANH" · ไม่มีที่อยู่ จำนวนห้อง หรือสิ่งอำนวยความสะดวกหลักในส่วนบนของหน้า (above the fold) · ประโยคอย่าง "stay on top of your career game" แทบไม่ได้บอกอะไร H1 ตัวเดียว ("A neighbourhood hotel in Ratchawat, Bangkok"), ย่อหน้าบอกตำแหน่งแบรนด์ (positioning) 3 บรรทัด, แถบข้อเท็จจริง (78 rooms · pool · gym · café · restaurant · 4 meeting rooms · Dusit) และคะแนนรีวิวของแขก
Positioning สื่อเรียก YANH ว่า "workation hotel" แต่เว็บไซต์แค่บอกเป็นนัย ("spaces made for work") ไม่มีอะไรพิสูจน์: ไม่มีความเร็ว Wi-Fi, การจัดโต๊ะทำงาน, ราคาพักระยะยาว หรือหน้า workspace ตัดสินใจ: จะเอาจริงด้วยหน้า Work & Stay (หลักฐานยืนยัน, ข้อเสนอพักระยะยาว, Groundwork ในฐานะ workspace) หรือเลิกกล่าวอ้าง
Meetings 4 หน้า หน้าละ 50–71 คำ · ไม่มีรูปแบบการจัดห้อง (layout), แพ็กเกจ, ราคาครึ่งวัน/เต็มวัน, รายละเอียดอาหาร (catering) หรือ AV · เป็นหน้า orphan (ดู Structure) ทำ Meetings hub หน้าเดียวที่มีตารางเปรียบเทียบ (ห้อง, ตร.ม., จำนวนที่นั่งตาม layout, AV, ราคาเริ่มต้น), แพ็กเกจ และฟอร์มสอบถามโดยเฉพาะ
Dining TANH ("The Morning Table of the Neighborhood") และ Groundwork (specialty coffee) ไม่มีเวลาเปิด-ปิด เมนู ราคา หรือข้อความว่า "เปิดให้บุคคลทั่วไปที่ไม่ได้เข้าพัก" · เป็นหน้า orphan ทำ Dining hub พร้อมเวลาเปิด เมนูตัวอย่าง ระดับราคา และรูปภาพ · ลิงก์จาก Home, Facilities และทุกหน้าห้องพัก
Offers title ของหน้า EN เป็นภาษาไทย · ข้อเสนอไม่ถูกนำไปแสดงที่อื่นในเว็บเลย แก้ title · นำข้อเสนอหลักไปแสดงบน Home และในหน้าห้องพัก
Blog & guide บทความ blog 1 บทความ (2023) กับฟอร์มขอข้อมูลสำหรับสื่อที่ถูกจัดเป็นโพสต์ blog · บทความย่าน 2 บทความ (2024) ในทางกลับกัน Instagram โพสต์สม่ำเสมอ (long stay, early bird, wellness weekends, collaborations) ทำจังหวะรายเดือน: แปลงธีมจาก Instagram เป็นคู่มือบนเว็บ · ย้ายฟอร์มสำหรับสื่อไปที่ /press
ข้อผิดพลาดใน copy "sogo dough" (ควรเป็น sago — สาคู) บนหน้าแรก · H1 ของ Cookies Policy เขียนว่า "Privacy Policy" · H1 ของ Terms เขียนว่า "Terms & Service" · footer ฝั่ง server เขียนว่า "Copyright undefined" · alt text เป็น "Our Story Image 01", "WELCOME TO" · caption ของ Instagram ใช้ตัวหนาแบบ Unicode ซึ่ง screen reader และ search engine อ่านไม่ได้ ตรวจทาน (proofread) ทั้งหมด · alt text ที่สื่อความหมาย · caption เป็นข้อความธรรมดา
การตั้งชื่อห้อง "Standard Quadruple" เป็นภาษาของ OTA แขกค้นหาว่า "family room" หรือ "room for 4" และมีคำว่า "YANH" นำหน้าชื่อห้องทุกห้อง คงชื่อ rate plan ไว้ แต่ใช้หัวข้อหลักว่า "Family Room with Bunk Beds (sleeps 4)"
TH / ZH tag และ description ปนภาษา (ดู Metadata) · copy ภาษาอังกฤษถูกนำไปใช้ใน meta ภาษาไทยและจีน ให้เจ้าของภาษาตรวจ title, description และ H1 ของ TH/ZH ทั้งหมด
หัวข้อที่ควรครองให้ได้ (Topics to own)
ไม่มีข้อมูลปริมาณการค้นหา (keyword volume) สำหรับการตรวจครั้งนี้ (ไม่มีสิทธิ์เข้า Search Console หรือเครื่องมือ keyword) ดังนั้นรายการนี้คือ intent ที่ต้องไปตรวจสอบต่อ ใน Search Console และ Google Keyword Planner ไม่ใช่เป้าหมายที่จัดอันดับความสำคัญแล้ว
Intent ภาษาอังกฤษ ภาษาไทย หน้าที่ควรติดอันดับ
แบรนด์ (Brand) YANH Ratchawat, YANH hotel Bangkok โรงแรมย่าน ราชวัตร Home
ทำเล (Location) hotel in Dusit Bangkok; hotel near Ratchawat Market; near Wat Benchamabophit โรงแรมย่านดุสิต; ที่พักใกล้ตลาดราชวัตร Home, หน้า Location
ดีไซน์ (Design) design hotel Bangkok; boutique hotel old Bangkok โรงแรมดีไซน์ กรุงเทพ Our Story
ทำงานและพักยาว (Work & long stay) workation hotel Bangkok; long-stay hotel Bangkok workation กรุงเทพ; ที่พักรายเดือน หน้า Work & Stay
ห้องประชุม (Meetings) meeting room Dusit; small meeting room Bangkok ห้องประชุม ราชวัตร; ห้องประชุม ดุสิต Meetings hub
อาหารและย่าน (Food & area) Ratchawat Market food; where to eat in Sriyan ร้านอร่อย ราชวัตร; ของกินศรีย่าน Neighbourhood guide
Staycation staycation Bangkok with pool staycation กรุงเทพ Offers
ครอบครัว (Family) family room Bangkok for 4 ห้องพัก 4 คน กรุงเทพ Standard Quadruple
intent ภาษาไทยมีโอกาสเติบโตสูงสุด: สื่อไทยรายงานเรื่อง YANH อยู่แล้ว ครีเอเตอร์บน Lemon8 ก็โพสต์ถึงในฐานะที่ staycation และเว็บภาษาไทยคือเว็บที่ข้อผิดพลาดเรื่อง canonical กำลังซ่อนไว้
07
Structure และ UX
เว็บไซต์ถูกสร้างแบบโบรชัวร์ ไม่ใช่เส้นทางสู่การจอง: 6 หน้าที่ขาย dining และ meetings ไม่มีลิงก์ภายในจากที่ใดเลย ปุ่มจองห้องเปิด booking engine ด้วยวันที่ที่ผ่านไปแล้ว และผู้เข้าชมชาวไทยถูกผลักไปหน้าภาษาอังกฤษ
ปัญหา หลักฐาน วิธีแก้
หน้าสร้างรายได้ที่เป็น orphan TANH, Groundwork และห้องประชุม 4 ห้อง (6 URL ฝั่ง EN + 12 URL ฝั่ง TH/ZH) ไม่ได้รับลิงก์จากเมนู, footer, หน้าแรก, Facilities หรือหน้าอื่นใด — เข้าถึงได้ผ่าน sitemap เท่านั้น บนหน้า Facilities คำว่า "TANH Restaurant", "GROUNDWORK Cafe" และ "Meeting Room & Event" เป็นข้อความธรรมดา ไม่ใช่ลิงก์ ใส่ Dining hub และ Meetings hub ในเมนูหลัก · ลิงก์ทุก tile ในหน้า Facilities
เมนูหลัก มีแค่ Our Story, Rooms, Special Offers, Our Neighborhoods, Contact ไม่มี Facilities, Dining หรือ Meetings และเมนู render ฝั่ง client จึงไม่มีอยู่ใน server HTML ทำเมนูตามแผนภาพด้านล่าง และ render ฝั่ง server
Booking deep links ลิงก์จองบนการ์ดห้องพัก hard-code วันเช็คอิน 29–31 กรกฎาคม 2026 (ผ่านไปแล้ว) และ locale=en แม้อยู่บนหน้า TH/ZH ส่วนปุ่ม "Book Now" บน header เปิด engine โดยไม่มีวันที่ ส่งวันนี้/พรุ่งนี้ หรือวันที่ที่แขกเลือก พร้อม locale ของหน้าและสกุลเงิน THB · เพิ่ม date picker ใน header
Attribution booking engine ทำงานบน book-directonline.com และโหลดทั้ง gtag.js และ gtm.js ยืนยัน GA4 cross-domain linking และการติดตาม purchase เพื่อให้รายได้จากการจองตรงถูกนับเป็นผลงานของเว็บไซต์และแคมเปญ
ภาษารั่ว ลิงก์ที่ไม่มี locale (ดู T5) ส่งผู้ใช้ TH/ZH ไปหน้าภาษาอังกฤษ ลิงก์ที่ผูกกับ locale (locale-aware)
หน้าที่วางผิดที่ Media & Influencer Request อยู่ใต้ /blog/ ย้ายไป /press และทำ 301
การตั้งชื่อ URL /food-and-drink/TANH, /meeting-room-and-event/TANH-2nd /dining/tanh, /meetings/tanh-2nd-floor (ตัวพิมพ์เล็ก) พร้อม 301
Contact มีฟอร์ม เบอร์โทร อีเมล แต่ไม่มีที่อยู่ แผนที่ หรือปุ่ม LINE ที่เด่นชัด (LINE เป็นแค่ไอคอนใน footer) ที่อยู่ภาษาอังกฤษและไทย, แผนที่, ปุ่ม LINE และโทรศัพท์เป็นปุ่มหลัก
น้ำหนักหน้าแรก ฝังโพสต์ Instagram 26 โพสต์เป็นลิงก์ออกนอกเว็บ feed นี้มีส่วนทำให้หน้าหนัก 5.7 MB และ desktop layout shift 0.705 แสดง 6 โพสต์ และโหลดเมื่อเลื่อนถึง
Footer server HTML มีแค่ลิงก์ด้านกฎหมายและ "Copyright undefined" footer ที่ render ฝั่ง server มีที่อยู่ เบอร์โทร LINE และลิงก์หน้าสำคัญ
Accessibility PSI: ปุ่มที่ไม่มี accessible name, ข้อความ contrast ต่ำ, alt text กว้างๆ ไม่สื่อความหมาย ใส่ label ให้ปุ่มไอคอน · เพิ่ม contrast · อธิบายรูปภาพ
โครงสร้างเว็บที่เสนอ · 8 ส่วน, hub ใหม่ 3 หน้า
Every revenue line one click from the homepage — ทุกช่องทางรายได้อยู่ห่างจากหน้าแรกเพียงคลิกเดียว
โครงสร้างที่เสนอสำหรับ yanhhotel.com เหมือนกันทั้ง EN, TH และ ZH
Home
เมนูหลัก (Main navigation) — render ฝั่ง server
Book and spend · จองและใช้จ่าย
Rooms
หน้าห้องพัก 6 หน้า Family Room สำหรับ 4 คน จองด้วยวันที่จริง (live dates)
Dining ใหม่
ร้านอาหาร TANH คาเฟ่ Groundwork เวลาเปิด เมนู ราคา
Meetings and Events ใหม่
4 ห้อง รองรับ 8–20 ที่นั่ง layout, AV, ราคา ฟอร์มสอบถาม
Offers
ดีลจองตรง Work and Stay (ใหม่) Staycation
Discover and trust · ค้นพบและสร้างความเชื่อมั่น
Our Story
ประวัติอาคาร CHAT Architects Press (ใหม่)
Neighbourhood
ตลาดราชวัตร P. Look Chin Sriyan คู่มือย่านรายเดือน
Facilities
สระว่ายน้ำ ยิม นวด ลิงก์ไป Dining ลิงก์ไป Meetings
Plan your stay ใหม่
ที่ตั้งและการเดินทาง FAQ ภาษา EN, TH, ZH Contact และ LINE
hub page ใหม่ หน้าที่มีอยู่แล้ว เก็บไว้และเขียนใหม่
แปดส่วนในเมนูเดียวที่ render ฝั่ง server ทำให้ห้องพัก, dining, meetings และ offers อยู่ห่างจาก Home เพียงคลิกเดียว และทำให้เนื้อหา FAQ และ location มีที่อยู่ถาวร
08
แผนปฏิบัติการ (Action plan)
งานแก้ P1 จำนวน 11 รายการ ใช้เวลาประมาณ 6 วันทำงานของนักพัฒนา, 2 วันของทีมคอนเทนต์ และ 1 วันของงานธุรการฝั่งการตลาด งานเหล่านี้กำจัดข้อผิดพลาดที่ซ่อนเว็บภาษาไทย ทำให้สำเนา staging รั่วออกไป และยกผลการค้นหาชื่อแบรนด์ให้ OTA ส่วน P2 คือการสร้างหน้าที่ขาย dining และ meetings และ P3 คือกลไกผลิตคอนเทนต์ต่อเนื่อง
ทั้งหมด (24)
P1 (11)
P2 (9)
P3 (4)
# งาน ผู้รับผิดชอบ Effort (ประมาณ) Priority สถานะ
1 ตั้ง self-canonical ให้ทุกหน้า TH และ ZH และตั้ง og:url ตาม locale (T1) นักพัฒนา 0.5 วัน P1 ขึ้น prod แล้ว
2 แก้บรรทัด Sitemap ใน robots.txt ให้ชี้ไปที่ www.yanhhotel.com (T2) นักพัฒนา 10 นาที P1 ขึ้น prod แล้ว
3 ตั้งรหัสผ่านป้องกัน www-uat, เพิ่ม noindex และลบ URL ของ UAT ที่ถูก index ออกผ่าน Search Console (T3) นักพัฒนา 0.5 วัน P1 บางส่วน noindex ขึ้น prod แล้ว · Search Console removal (marketing) · IAP (infra)
4 แก้ canonical 6 จุดที่ชี้ไปหน้า 404 (T4) นักพัฒนา 1 ชั่วโมง P1 ขึ้น prod แล้ว หายพร้อม T1 (self-canonical)
5 ทำให้ลิงก์ภายในทุกลิงก์ผูกกับ locale (T5) นักพัฒนา 1 วัน P1 ขึ้น prod แล้ว
6 Server-render เนื้อหาหน้าแรก, เมนูหลัก และ footer (ที่อยู่, เบอร์โทร, copyright) นักพัฒนา 2–3 วัน P1 ขึ้น prod แล้ว
7 ลิงก์จอง: ใช้วันที่จริง, locale ของหน้า และ THB · เพิ่ม date picker ใน header นักพัฒนา 0.5 วัน P1 บางส่วน ลิงก์: วันที่/ภาษา/THB ขึ้น prod แล้ว · date picker ใน header ทำทีหลัง
8 title, description ใหม่ และ H1 เดียวต่อหน้าสำหรับทั้ง 27 หน้า EN · ชุด TH และ ZH โดยเจ้าของภาษา ทีมคอนเทนต์ 2 วัน P1 บางส่วน โค้ดครบ (H1 + SEO แยกภาษา + suffix) ขึ้น prod แล้ว รอ backfill · ข้อความ title/description ใหม่เป็นงาน content
9 JSON-LD ของ Hotel, HotelRoom และ BreadcrumbList ใน layout และ template ห้องพัก นักพัฒนา 1 วัน P1 ขึ้น prod แล้ว geo, จำนวนห้อง, check-in/out รอโรงแรมยืนยัน
10 ชี้ Google Business Profile, extranet ของ OTA, Facebook, Instagram และ LINE มาที่ yanhhotel.com · ปรับการสะกดที่อยู่ให้ตรงกัน การตลาด / ฝ่ายรายได้ (Revenue) 1 วัน P1 ยังไม่เริ่ม
11 Verify Search Console สำหรับ www และ www-uat · submit sitemap · ตั้ง baseline อันดับคำค้นชื่อแบรนด์และการ index ของ TH/ZH การตลาด 2 ชั่วโมง P1 ยังไม่เริ่ม
12 สร้าง Dining hub และ Meetings hub · เปลี่ยน slug เป็นตัวพิมพ์เล็กพร้อม 301 · เพิ่มในเมนู · ลิงก์ tile ใน Facilities (T7, T8) นักพัฒนา + ทีมคอนเทนต์ 1 สัปดาห์ P2 ยังไม่เริ่ม
13 หน้า Location & Getting Here และ FAQ ภาษา EN/TH/ZH พร้อม FAQPage markup ทีมคอนเทนต์ 1 สัปดาห์ P2 ยังไม่เริ่ม
14 schema ของ Restaurant, CafeOrCoffeeShop และ MeetingRoom นักพัฒนา 0.5 วัน P2 ขึ้น prod แล้ว
15 Performance: cache header, น้ำหนักรูป, เลื่อนการโหลด Instagram feed, แก้ desktop CLS 0.705, ตัด request ที่บล็อกการ render นักพัฒนา 3–5 วัน P2 บางส่วน
16 og:image เฉพาะหน้าบนทุก URL นักพัฒนา 0.5 วัน P2 ขึ้น prod แล้ว
17 ใช้วันที่ lastmod จริงใน sitemap (T6) นักพัฒนา 0.5 วัน P2 ขึ้น prod แล้ว
18 ใช้ Google tag ตัวเดียวผ่าน GTM · GA4 cross-domain ไปยัง booking engine · event purchase (T10) นักพัฒนา + การตลาด 1 วัน P2 บางส่วน CSP ที่บล็อก GA4 แก้แล้ว · cross-domain รอ marketing
19 ตรวจทาน (sago, H1), alt text ที่สื่อความหมาย, label ปุ่มที่ accessible, contrast ทีมคอนเทนต์ + นักพัฒนา 1 วัน P2 บางส่วน ส่วน dev เสร็จ (label ปุ่ม, alt ทุกจุด, H1) · เหลือ contrast (ดีไซน์) และ "sago" (content)
20 หน้า Press · ให้เครดิต CHAT Architects ใน Our Story · แสดงคะแนนรีวิวของแขกบน Home และ Rooms ทีมคอนเทนต์ 2 วัน P2 ยังไม่เริ่ม
21 หน้า Work & Stay พร้อมหลักฐานยืนยันและข้อเสนอพักระยะยาว — ทำเฉพาะเมื่อยืนยัน positioning แล้ว GM + ทีมคอนเทนต์ 3 วัน P3 ยังไม่เริ่ม
22 คู่มือย่านรายเดือน (EN/TH/ZH) โดยดึงจากธีมใน Instagram ทีมคอนเทนต์ ต่อเนื่อง P3 ยังไม่เริ่ม
23 ย้ายฟอร์มสำหรับสื่อไป /press · คืน 404 สำหรับ path ระดับ root ที่ไม่รู้จัก (T9) นักพัฒนา 2 ชั่วโมง P3 ขึ้น prod แล้ว
24 ร้องเรียนด้านแบรนด์หรือต่อ registrar กับโดเมน clone หลังจากสัญญาณทางการขึ้นระบบแล้ว เจ้าของ + ที่ปรึกษากฎหมาย — P3 ยังไม่เริ่ม
ข้อมูลที่ต้องได้จากโรงแรมก่อนจะปิดงาน P1/P2 ได้: สิทธิ์เข้า Search Console และ GA4 · สิทธิ์เข้า Google Business Profile · สิทธิ์ admin ของ booking engine · การยืนยันเวลา check-in/out, เวลาและราคาอาหารเช้า, เงื่อนไขที่จอดรถ, นโยบายสัตว์เลี้ยงและรถรับส่งสนามบิน · ราคาและแพ็กเกจห้องประชุม · รายการข้อเสนอที่เปิดขายอยู่ · ปีที่เปิดให้บริการ
09
แหล่งข้อมูล (Sources)
yanhhotel.com/en , robots.txt , sitemap.xml และ 81 URL ที่อยู่ใน sitemap — crawl เมื่อ 5 ตุลาคม 2026
www-uat.yanhhotel.com (staging host) — ตรวจเมื่อ 5 ตุลาคม 2026
รายงาน PageSpeed Insights หน้าแรก — 5 ตุลาคม 2026
รายการบน Trip.com — ที่อยู่, 78 ห้อง, คะแนน 9.2/10 จาก 297 รีวิว
art4d, "YANH RATCHAWAT: Revamping an old building" — CHAT Architects, SC Asset, ประวัติอาคาร
yanhratchawat.com-bangkok.com — เว็บจองที่ไม่เป็นทางการ และข้อความปฏิเสธความเป็นทางการ (disclaimer) ของเว็บนั้น
ต้นฉบับ PDF ฝังลิงก์ของ PageSpeed Insights, Trip.com, art4d และเว็บ clone ไว้ แต่ URL เต็มไม่ติดมาในข้อความที่ดึงออกจาก PDF ฉบับแปลนี้จึงใส่ลิงก์เฉพาะ URL ที่ระบุชัดในเนื้อหา
ภาคผนวก
คำอธิบายศัพท์ (ผู้แปลเพิ่มเติม)
ศัพท์ ความหมาย
AEO Answer Engine Optimization — การปรับเว็บให้ AI/answer engine (ChatGPT, Perplexity, Gemini, Google AI Mode) ดึงข้อมูลไปตอบและอ้างอิงได้ถูกต้อง
canonical rel=canonical — tag ที่บอก search engine ว่า URL ไหนคือ "ต้นฉบับ" ของเนื้อหา หน้าที่ชี้ canonical ไปที่อื่นจะถูกมองว่าเป็นหน้าซ้ำและมักไม่ถูก index
self-canonical หน้าที่ตั้ง canonical ชี้มาที่ URL ของตัวเอง
hreflang tag ที่บอกว่าแต่ละหน้ามีเวอร์ชันภาษาอื่นที่ URL ใด (en, th, zh, x-default)
OTA Online Travel Agency — เว็บตัวกลางจองที่พัก เช่น Booking.com, Trip.com, Traveloka ซึ่งเก็บค่าคอมมิชชันจากโรงแรม
orphan page หน้าที่ไม่มีลิงก์ภายในใดชี้เข้า เข้าถึงได้ทาง sitemap หรือ URL ตรงเท่านั้น
server- / client-rendered เนื้อหาที่มาพร้อม HTML จาก server เทียบกับเนื้อหาที่ JavaScript ดึงมาแสดงภายหลังในเบราว์เซอร์ (crawler ที่ไม่รัน JS จะไม่เห็น)
JSON-LD / schema ข้อมูลโครงสร้างตามมาตรฐาน schema.org ที่ฝังในหน้า เพื่อบอกเครื่องว่าหน้านี้คือโรงแรม ห้องพัก ร้านอาหาร ฯลฯ
NAP Name, Address, Phone — ชื่อ ที่อยู่ เบอร์โทร ที่ควรเหมือนกันทุกแหล่ง
soft-404 URL ที่ไม่มีอยู่จริงแต่ตอบกลับ 200 (เช่น redirect ไปหน้าแรก) แทนที่จะเป็น 404
LCP / FCP / TBT / CLS ตัวชี้วัดความเร็ว: เวลาที่องค์ประกอบใหญ่สุดแสดง / เวลาที่เนื้อหาแรกแสดง / เวลาที่ main thread ถูกบล็อก / ปริมาณการกระโดดของ layout
og:image / og:url Open Graph tag ที่ใช้กำหนดรูปและ URL ตอนแชร์ลิงก์บน LINE, Facebook, WhatsApp
lastmod วันที่แก้ไขล่าสุดของแต่ละ URL ใน sitemap ใช้ช่วย Google จัดลำดับการ crawl ซ้ำ
link equity "คะแนน" ที่ส่งผ่านลิงก์ภายใน/ภายนอก ซึ่งลดลงเมื่อผ่าน redirect
cross-domain linking การตั้ง GA4 ให้ติดตาม session ต่อเนื่องข้ามโดเมน (yanhhotel.com → book-directonline.com) เพื่อให้นับยอดจองตรงได้ถูกต้อง
Search Console / GBP Google Search Console (เครื่องมือดูการ index และคำค้น) / Google Business Profile (ข้อมูลธุรกิจบน Google Maps และ Search)