|
WEBFIX REPORT แผนแก้ไขเว็บแบบ step-by-step สำหรับ Developer |
[โดเมนลูกค้า]
[ชื่อลูกค้า] ([ชื่อลูกค้า] [จังหวัด])
16 สิงหาคม 2569
Profile C — AI-Native
Methodology: v2.0
คะแนนปัจจุบัน 46/100 (เกรด D) → คาดหวังหลังแก้ครบ 88/100 (เกรด A)
อ้างอิงผลจาก: [ชื่อลูกค้า].docx
จำนวน Ticket ทั้งหมด
|
P0 Critical |
P1 High |
P2 Medium |
P3 Low |
|
4 ใบ |
7 ใบ |
9 ใบ |
4 ใบ |
รวม 24 ticket สำหรับ developer + 6 รายการ off-site ที่ลูกค้าต้องทำเอง
1 Score Summary คะแนนปัจจุบัน เทียบ คาดหวังหลังแก้แต่ละ Phase
|
Dimension |
น้ำหนัก |
ปัจจุบัน |
Phase 1 |
Phase 2 |
Phase 3 (เป้าหมาย) |
|
Crawlability |
15% |
52 |
79 |
79 |
79 |
|
Content Understandability |
20% |
15 |
60 |
95 |
100 |
|
AI Citation Presence |
25% |
85 |
85 |
85 |
85 |
|
Technical Performance |
10% |
87 |
87 |
87 |
89 |
|
AI Overview Presence |
30% |
19 |
43 |
76 |
92 |
|
คะแนนรวม (Weighted) |
46 |
61 |
78 |
88 (เกรด A) |
หมายเหตุ: คะแนน Phase 2 และ 3 ในส่วน AI Overview รวมผลของงาน off-site ซึ่งต้องรอ index หลายวันถึงหลายสัปดาห์ ตอน re-audit อาจยังขึ้นเป็น PARTIAL แม้ทำครบแล้ว
2 P0 — Critical Tickets blocker ที่ต้องแก้ภายใน 48 ชั่วโมง
|
#001 |
P0 |
ปลดบล็อก GPTBot และ meta-externalagent ที่ Hostinger CDN |
|
Dimension |
Crawlability |
|
หน้าที่แก้ |
ทั้งโดเมน — ระดับ CDN / hPanel ไม่ใช่ระดับไฟล์ |
|
ส่วนที่แก้ |
Hostinger hPanel > Security หรือ Website > สวิตช์บล็อก AI crawler (edge rule ที่ server: hcdn) |
|
ปัญหา |
User-Agent ที่มีเลขเวอร์ชันจริงอย่าง GPTBot/1.2 และ meta-externalagent/1.1 ถูกตอบด้วย HTTP 429 พร้อม content-length เป็น 0 ทดสอบซ้ำ 3 รอบได้ผลเหมือนกันทุกครั้ง ยืนยันว่าไม่ใช่ rate limit ชั่วคราว เพราะ bot ตัวอื่นที่มีเลขเวอร์ชันเหมือนกัน (PerplexityBot/1.0, Amazonbot/0.1, Applebot/0.1) ผ่านได้ปกติ และ response ถูกส่งจาก edge (server: hcdn) ไม่ใช่จาก PHP ผลกระทบจริงคือ GPTBot เป็นตัวที่ OpenAI ใช้เก็บเนื้อหาเข้าคลังความรู้ถาวร เมื่อถูกบล็อก ChatGPT จึงไม่มีวันจำร้านนี้ได้เอง ส่วน OAI-SearchBot และ ChatGPT-User ที่ผ่านได้ทำให้ ChatGPT เปิดดูเว็บได้เฉพาะตอนผู้ใช้ถามเท่านั้น |
วิธีแก้
Code / คำสั่งที่ใช้
|
# ทดสอบก่อนแก้ — ปัจจุบันได้ 429 สองตัว |
|
for ua in "GPTBot/1.2 (+https://openai.com/gptbot)" \ |
|
"meta-externalagent/1.1 (+https://developers.facebook.com/docs/sharing/webmasters/crawler)" \ |
|
"ClaudeBot/1.0" "PerplexityBot/1.0" "Googlebot/2.1"; do |
|
printf '%-24s -> ' "$(echo $ua | cut -d/ -f1)" |
|
curl -sS -A "$ua" -o /dev/null -w '%{http_code}\n' https://[โดเมนลูกค้า]/ |
|
done |
|
|
|
# ผลที่ถูกต้องหลังแก้ = 200 ทั้ง 5 ตัว |
|
# ผลปัจจุบัน (16 ส.ค. 2569): |
|
# GPTBot -> 429 <-- ต้องแก้ |
|
# meta-externalagent -> 429 <-- ต้องแก้ |
|
# ClaudeBot -> 200 |
|
# PerplexityBot -> 200 |
|
# Googlebot -> 200 |
|
ผลที่คาดหวัง GPTBot เข้าเก็บเนื้อหาได้ภายในรอบ crawl ถัดไป (ปกติ 1–4 สัปดาห์) · ChatGPT เริ่มมีข้อมูลร้านในคลังความรู้แทนที่จะต้องเปิดเว็บดูสดทุกครั้ง |
Score Impact +4.1 pts (Bot Simulation 0 → 100) |
เวลาประมาณ 15–30 นาที (ถ้าต้องเปิด ticket กับ Hostinger รอเพิ่ม 1–2 วัน) |
|
#002 |
P0 |
ใส่เมนูจริงพร้อมราคาลงหน้า /menu.php แล้วผูก Restaurant + Menu schema |
|
Dimension |
AI Overview / Content |
|
หน้าที่แก้ |
https://[โดเมนลูกค้า]/menu.php |
|
ส่วนที่แก้ |
<div class='container aa-meal'> — ตอนนี้ทั้ง div มีแค่ปุ่ม LINE หนึ่งปุ่ม |
|
ปัญหา |
หน้าเมนูของร้านอาหารไม่มีเมนู ทั้งหน้ามีแค่ h1 'เมนู' ข้อความบรรยาย 3 บรรทัด และปุ่ม LINE หนึ่งปุ่ม ไม่มีชื่ออาหารสักจาน ไม่มีราคาสักตัว ไม่มี Menu schema ขณะที่ราคาจริงถูกเผยแพร่อยู่บนเว็บภายนอกแล้ว ผลคือเมื่อมีคนถาม AI ว่าร้านนี้ราคาเท่าไร AI จะไปหยิบคำตอบจาก Wongnai และเว็บรีวิว ไม่ใช่จากเว็บของร้าน แบรนด์จึงเสียสิทธิ์ควบคุมข้อมูลราคาของตัวเองทั้งหมด นี่คือ ticket ที่ให้ผลตอบแทนสูงที่สุดในเอกสารนี้ เพราะแก้ทีเดียวได้คะแนนจาก 3 มิติพร้อมกัน |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- โครงหน้า /menu.php ที่ต้องมี --> |
|
<h1>เมนูและราคา — [ชื่อลูกค้า]</h1> |
|
|
|
<h2>สำรับป้าอี้ (1 ท่าน) — 3,300 บาท++</h2> |
|
<ul> |
|
<li>[ชื่อจานที่ 1] — [คำอธิบายสั้น 1 บรรทัด]</li> |
|
<li>[ชื่อจานที่ 2] — [คำอธิบายสั้น 1 บรรทัด]</li> |
|
</ul> |
|
|
|
<h2>สำรับป้าขันทอง (1 ท่าน) — 2,900 บาท++</h2> |
|
<h2>สำรับรองท้อง (2 ท่าน) — 2,400 บาท++</h2> |
|
<h2>อาหารตามสั่ง (a la carte) — เริ่มต้น 320 บาท</h2> |
|
<h2>ล่องเรือย้อนรอยแม่น้ำ 3 สาย — 3,500 บาท++ ต่อชั่วโมง (สูงสุด 6 ท่าน)</h2> |
|
|
|
<p>ราคายังไม่รวม service charge · สำรองที่นั่งล่วงหน้าเท่านั้น |
|
โทร <a href="tel:[เบอร์โทรลูกค้า]">[เบอร์โทรลูกค้า]</a> หรือ LINE |
|
<a href="https://[LINE ลูกค้า]">[บัญชีโซเชียลลูกค้า]</a></p> |
|
|
|
<!-- JSON-LD — วางใน <head> ของ /menu.php --> |
|
<script type="application/ld+json"> |
|
{ |
|
"@context": "https://schema.org", |
|
"@type": "Restaurant", |
|
"@id": "https://[โดเมนลูกค้า]/#restaurant", |
|
"name": "[ชื่อลูกค้า]", |
|
"alternateName": "[ชื่อลูกค้า] [จังหวัด]", |
|
"url": "https://[โดเมนลูกค้า]/", |
|
"servesCuisine": ["Thai", "อาหารไทยพื้นบ้าน", "อาหารตำรับ[จังหวัด]"], |
|
"priceRange": "2400-3300 THB", |
|
"acceptsReservations": "True", |
|
"telephone": "[เบอร์โทรลูกค้า]", |
|
"hasMenu": { |
|
"@type": "Menu", |
|
"name": "สำรับ [ชื่อลูกค้า]", |
|
"inLanguage": "th-TH", |
|
"hasMenuSection": [ |
|
{ |
|
"@type": "MenuSection", |
|
"name": "สำรับป้าอี้", |
|
"description": "สำรับอาหารไทยพื้นบ้านสำหรับ 1 ท่าน", |
|
"offers": { "@type": "Offer", "price": "3300", "priceCurrency": "THB" } |
|
}, |
|
{ |
|
"@type": "MenuSection", |
|
"name": "สำรับป้าขันทอง", |
|
"offers": { "@type": "Offer", "price": "2900", "priceCurrency": "THB" } |
|
}, |
|
{ |
|
"@type": "MenuSection", |
|
"name": "สำรับรองท้อง (2 ท่าน)", |
|
"offers": { "@type": "Offer", "price": "2400", "priceCurrency": "THB" } |
|
} |
|
] |
|
} |
|
} |
|
</script> |
|
ผลที่คาดหวัง AI ตอบคำถามเรื่องราคาและเมนูจากเว็บของร้านเองแทนที่จะไปดึงจาก Wongnai · หน้าเมนูมีสิทธิ์ขึ้น rich result และถูกเลือกเป็นแหล่งอ้างอิงใน AI Overview |
Score Impact +8.1 pts (Snippet Readiness 10 → 70 · ปลดค่าปรับ thin content −15 · Tier 2 schema) |
เวลาประมาณ 3–4 ชั่วโมง (หลังได้ไฟล์เมนูจากลูกค้า) |
|
#003 |
P0 |
แก้ลิงก์ /en/ ที่เป็นทางตัน 45 จุด และตัดสินใจเรื่องเว็บภาษาอังกฤษ |
|
Dimension |
Crawlability / Content |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า — ปุ่ม TH/EN อยู่ใน nav ทั้ง 3 ชุด · /en/ และทุก URL ใต้ /en/ |
|
ส่วนที่แก้ |
<a href='/en/...' class='mod-lang'> ใน .ftmenu, .topmenu และ .so-nav · และ <html lang> · rewrite rule ของ /en/ |
|
ปัญหา |
ทุกหน้ามีปุ่มสลับภาษา TH/EN ชี้ไป /en/ รวม 45 ลิงก์ทั่วเว็บ แต่ทดสอบแล้วทุก URL ใต้ /en/ ตอบ HTTP 301 ไปที่ http://www.[โดเมนลูกค้า]/ ซึ่งเป็น http ไม่ใช่ https แล้ววิ่งต่ออีก 2 ครั้งจนกลับมาจบที่หน้าภาษาไทยเดิม รวม 3 redirect ต่อการคลิกหนึ่งครั้ง แปลว่านักท่องเที่ยวต่างชาติที่กดปุ่ม EN จะถูกโยนกลับมาหน้าไทยโดยไม่มีอะไรอธิบาย สำหรับร้านอาหารในเมืองมรดกโลกที่ตลาดหลักคือชาวต่างชาติ นี่คือการปิดประตูใส่ลูกค้ากลุ่มใหญ่ที่สุดกลุ่มหนึ่ง ซ้ำร้ายทุกหน้ายังตั้ง translate='no' และ class='notranslate' ซึ่งห้ามแม้แต่ Google Translate ไม่ให้แปลหน้าให้ผู้อ่านต่างชาติ |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- ทางเลือก A — บนหน้าไทยทุกหน้า --> |
|
<html lang="th"> |
|
<link rel="alternate" hreflang="th-TH" href="https://[โดเมนลูกค้า]/menu.php" /> |
|
<link rel="alternate" hreflang="en" href="https://[โดเมนลูกค้า]/en/menu.php" /> |
|
<link rel="alternate" hreflang="x-default" href="https://[โดเมนลูกค้า]/menu.php" /> |
|
|
|
<!-- บนหน้า /en/ ทุกหน้า --> |
|
<html lang="en"> |
|
<link rel="alternate" hreflang="th-TH" href="https://[โดเมนลูกค้า]/menu.php" /> |
|
<link rel="alternate" hreflang="en" href="https://[โดเมนลูกค้า]/en/menu.php" /> |
|
<link rel="alternate" hreflang="x-default" href="https://[โดเมนลูกค้า]/menu.php" /> |
|
|
|
<!-- ถอดสองค่านี้ออกจาก <html> ทุกหน้า --> |
|
<!-- ผิด --> <html lang="th" class="notranslate" translate="no"> |
|
<!-- ถูก --> <html lang="th"> |
|
|
|
# ทดสอบว่า /en/ ยังเป็นทางตันอยู่ไหม |
|
for p in "" about.php menu.php contact.php; do |
|
printf '/en/%-14s -> ' "$p" |
|
curl -sS -o /dev/null -w '%{http_code} -> %{redirect_url}\n' "https://[โดเมนลูกค้า]/en/$p" |
|
done |
|
# ผลปัจจุบัน: 301 -> http://www.[โดเมนลูกค้า]/... (วน 3 ครั้งกลับหน้าไทย) |
|
ผลที่คาดหวัง ทางเลือก A ทำให้เว็บมีเนื้อหาภาษาอังกฤษให้ AI อ้างอิงเมื่อมีคนถามเป็นภาษาอังกฤษ และเปิดตลาดนักท่องเที่ยวต่างชาติ · ทางเลือก B อย่างน้อยเลิกทำให้ผู้ใช้เจอทางตัน |
Score Impact +6.3 pts ถ้าเลือกทางเลือก A · +1.5 pts ถ้าเลือกทางเลือก B |
เวลาประมาณ ทางเลือก A 2–3 วัน (รวมงานแปล) · ทางเลือก B 30 นาที |
|
#004 |
P0 |
สร้าง robots.txt และ sitemap.xml (ตอนนี้ 404 ทั้งคู่) |
|
Dimension |
Crawlability |
|
หน้าที่แก้ |
https://[โดเมนลูกค้า]/robots.txt · https://[โดเมนลูกค้า]/sitemap.xml |
|
ส่วนที่แก้ |
ไฟล์ static ที่ document root |
|
ปัญหา |
ตรวจ /robots.txt, /sitemap.xml, /sitemap_index.xml และ /sitemap.txt ได้ HTTP 404 ทั้งหมด สิ่งที่เสิร์ฟกลับมาคือหน้า This Page Does Not Exist ของ Hostinger ผลคือ search engine และ AI crawler ไม่มีแผนที่เว็บให้เดิน ต้องเดาจากการไล่ลิงก์เอาเอง และเว็บเสียคะแนน Sitemap/Indexability ไปเต็มจำนวน ข้อดีคือการไม่มี robots.txt ไม่ได้บล็อกใคร Google-Extended จึงยังได้เต็ม 100 อยู่ แต่ต้องระวังไม่ให้ robots.txt ตัวใหม่ไปบล็อกอะไรโดยไม่ตั้งใจ |
วิธีแก้
Code / คำสั่งที่ใช้
|
# /robots.txt |
|
User-agent: * |
|
Allow: / |
|
|
|
# อนุญาต AI crawler ทุกตัวอย่างชัดเจน |
|
User-agent: GPTBot |
|
Allow: / |
|
User-agent: OAI-SearchBot |
|
Allow: / |
|
User-agent: ChatGPT-User |
|
Allow: / |
|
User-agent: ClaudeBot |
|
Allow: / |
|
User-agent: PerplexityBot |
|
Allow: / |
|
User-agent: Google-Extended |
|
Allow: / |
|
User-agent: meta-externalagent |
|
Allow: / |
|
|
|
Sitemap: https://[โดเมนลูกค้า]/sitemap.xml |
|
|
|
<!-- /sitemap.xml --> |
|
<?xml version="1.0" encoding="UTF-8"?> |
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> |
|
<url><loc>https://[โดเมนลูกค้า]/</loc><priority>1.0</priority></url> |
|
<url><loc>https://[โดเมนลูกค้า]/about.php</loc><priority>0.8</priority></url> |
|
<url><loc>https://[โดเมนลูกค้า]/menu.php</loc><priority>0.9</priority></url> |
|
<url><loc>https://[โดเมนลูกค้า]/awards.php</loc><priority>0.8</priority></url> |
|
<url><loc>https://[โดเมนลูกค้า]/gallery.php</loc><priority>0.6</priority></url> |
|
<url><loc>https://[โดเมนลูกค้า][หน้าวิดีโอ]</loc><priority>0.6</priority></url> |
|
<url><loc>https://[โดเมนลูกค้า]/contact.php</loc><priority>0.9</priority></url> |
|
<url><loc>https://[โดเมนลูกค้า]/blog/</loc><priority>0.7</priority></url> |
|
<!-- บทความ — ต้อง percent-encode อักขระไทยใน path --> |
|
<url><loc>https://[โดเมนลูกค้า]/blog/1/%E0%B8%A5%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B9%80%E0%B8%A3%E0%B8%B7%E0%B8%AD/</loc> |
|
<lastmod>2024-11-21</lastmod></url> |
|
<!-- ทำแบบเดียวกันกับบทความที่ 2 ถึง 7 --> |
|
</urlset> |
|
|
|
# verify |
|
curl -sI https://[โดเมนลูกค้า]/robots.txt | head -1 # ต้องได้ 200 |
|
curl -sI https://[โดเมนลูกค้า]/sitemap.xml | head -1 # ต้องได้ 200 |
|
curl -s https://[โดเมนลูกค้า]/sitemap.xml | xmllint --noout - # ต้องไม่มี error |
|
ผลที่คาดหวัง Google และ AI crawler เห็นหน้าทั้ง 15 หน้าครบภายใน 3–14 วันหลัง submit · หน้าที่เคยเข้าถึงได้ยากถูก index เร็วขึ้น |
Score Impact +1.8 pts (Sitemap/Indexability 0 → 50) |
เวลาประมาณ 1–2 ชั่วโมง |
3 P1 — High Priority Tickets ผลกระทบสูง แก้ภายใน 2 สัปดาห์
|
#005 |
P1 |
ใส่ Restaurant + Organization schema พร้อม sameAs และ NAP ที่ถูกต้อง ทุกหน้า |
|
Dimension |
AI Overview / Content |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า — วาง JSON-LD ใน <head> ของ template กลาง |
|
ส่วนที่แก้ |
<script type='application/ld+json'> ใน <head> |
|
ปัญหา |
ทั้งเว็บมี JSON-LD แค่ block เดียวคือ VideoObject บนหน้าแรก ไม่มี Organization, LocalBusiness หรือ Restaurant เลยสักตัว ทำให้ Tier 1 ของ Schema Eligibility ได้เพียง 5 จาก 50 คะแนน AI จึงไม่มีระเบียนที่บอกว่าธุรกิจนี้คือใคร อยู่ที่ไหน เปิดกี่โมง ติดต่อยังไง และมีรางวัลอะไร ทั้งที่ข้อมูลทั้งหมดนี้มีอยู่จริงและตรวจสอบได้ |
วิธีแก้
Code / คำสั่งที่ใช้
|
<script type="application/ld+json"> |
|
{ |
|
"@context": "https://schema.org", |
|
"@type": "Restaurant", |
|
"@id": "https://[โดเมนลูกค้า]/#restaurant", |
|
"name": "[ชื่อลูกค้า]", |
|
"alternateName": "[ชื่อลูกค้า] [จังหวัด]", |
|
"description": "ร้านอาหารไทยพื้นบ้า[ชื่อลูกค้ารายอื่น] ชุมชน[อำเภอ/ตำบล] จังหวัด[จังหวัด] สืบทอดสูตรอาหารตำรับชาวบ้านจากแม่ ป้า ย่า ยาย ในชุมชน", |
|
"url": "https://[โดเมนลูกค้า]/", |
|
"logo": "https://[โดเมนลูกค้า]/svg/aa-color.svg", |
|
"image": "https://[โดเมนลูกค้า]/hero_rv3.jpg", |
|
"telephone": "[เบอร์โทรลูกค้า]", |
|
"email": "[ยืนยันกับลูกค้า — แหล่งภายนอกระบุ [อีเมลลูกค้า]]", |
|
"address": { |
|
"@type": "PostalAddress", |
|
"streetAddress": "[ยืนยันกับลูกค้า — แหล่งภายนอกระบุ [เลขที่]]", |
|
"addressLocality": "[อำเภอ/ตำบล]", |
|
"addressRegion": "[จังหวัด]", |
|
"postalCode": "[รหัสไปรษณีย์]", |
|
"addressCountry": "TH" |
|
}, |
|
"geo": { "@type": "GeoCoordinates", "latitude": 14.300886, "longitude": 100.560414 }, |
|
"openingHoursSpecification": [{ |
|
"@type": "OpeningHoursSpecification", |
|
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"], |
|
"opens": "11:00", "closes": "21:00" |
|
}], |
|
"servesCuisine": ["Thai", "อาหารไทยพื้นบ้าน"], |
|
"priceRange": "2400-3300 THB", |
|
"acceptsReservations": "True", |
|
"award": [ |
|
"[รางวัลออกแบบระดับสากล] — Social Impact ([สื่อออกแบบต่างประเทศ], Italy)", |
|
"[รางวัลร้านอาหารระดับสากล] ([นิตยสารต่างประเทศ], UK)", |
|
"[รางวัลอาหารไทยระดับประเทศ] (กระทรวงพาณิชย์)" |
|
], |
|
"sameAs": [ |
|
"https://www.facebook.com/[ชื่อลูกค้า]/", |
|
"https://instagram.com/[ชื่อลูกค้า]", |
|
"https://www.youtube.com/[บัญชีโซเชียลลูกค้า]", |
|
"https://[LINE ลูกค้า]" |
|
] |
|
} |
|
</script> |
|
|
|
# verify ว่ายิงจาก server-side จริง — ต้องเจอใน raw HTML |
|
curl -s https://[โดเมนลูกค้า]/ | grep -c '"@type": "Restaurant"' # ต้องได้ >= 1 |
|
ผลที่คาดหวัง AI มีระเบียนที่บอกได้ว่าร้านนี้คือใคร อยู่ที่ไหน เปิดกี่โมง ราคาเท่าไร และได้รางวัลอะไร · มีสิทธิ์ขึ้น local rich result |
Score Impact +5.6 pts (Tier 1 Core 5 → 45) |
เวลาประมาณ 2 ชั่วโมง |
|
#006 |
P1 |
เขียน title และ meta description ใหม่ให้ไม่ซ้ำกันทั้ง 15 หน้า |
|
Dimension |
Content |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า |
|
ส่วนที่แก้ |
<title> และ <meta name='description'> ใน <head> |
|
ปัญหา |
ทุกหน้าตั้งแต่หน้าแรก เกี่ยวกับเรา เมนู บทความ วิดีโอ แกลเลอรี่ รางวัล ติดต่อเรา ไปจนถึงบทความทั้ง 7 บท ใช้ <title>[ชื่อลูกค้า]</title> เหมือนกันทุกตัวอักษร และใช้ meta description ก้อนเดียวกันทั้งหมด ผลคือ Google และ AI แยกไม่ออกว่าหน้าไหนพูดเรื่องอะไร และผลการค้นหาจะแสดงรายการที่หน้าตาเหมือนกันหมดจนคนไม่รู้จะคลิกอันไหน |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- หน้าแรก --> |
|
<title>[ชื่อลูกค้า] | ร้านอาหารไทยพื้นบ้านริมน้ำ [จังหวัด]</title> |
|
<meta name="description" content="ร้านอาหารไทยพื้นบ้า[ชื่อลูกค้ารายอื่น] ชุมชน[อำเภอ/ตำบล] [จังหวัด] สืบทอดสูตรจากแม่ ป้า ย่า ยาย ในอาคารบล็อกแก้วรางวัล [นิตยสารต่างประเทศ] เปิดทุกวัน 11.00-21.00 น."> |
|
|
|
<!-- /menu.php --> |
|
<title>เมนูและราคาสำรับ | [ชื่อลูกค้า] [จังหวัด]</title> |
|
<meta name="description" content="เมนูและราคาสำรับอาหารไทยพื้นบ้านของ [ชื่อลูกค้า] สำรับป้าอี้ สำรับป้าขันทอง สำรับรองท้อง และล่องเรือแม่น้ำ สำรองที่นั่งล่วงหน้า โทร [เบอร์โทรลูกค้า]"> |
|
|
|
<!-- /about.php --> |
|
<title>เกี่ยวกับเรา ชุมชน[อำเภอ/ตำบล] | [ชื่อลูกค้า]</title> |
|
<meta name="description" content="เรื่องราวของ [ชื่อลูกค้า] [จังหวัด] จากชุมชน[อำเภอ/ตำบล] อาคารบล็อกแก้ว 20,000 ก้อน ภาชนะดินเผาทำมือ และสูตรอาหารที่สืบทอดจากสตรีสูงวัยในชุมชน"> |
|
|
|
<!-- /awards.php --> |
|
<title>รางวัล [นิตยสารต่างประเทศ] และ [รางวัลอาหารไทยระดับประเทศ] 2024 | [ชื่อลูกค้า]</title> |
|
<meta name="description" content="[ชื่อลูกค้า] เจ้าของรางวัล [รางวัลออกแบบระดับสากล] จาก [สื่อออกแบบต่างประเทศ][รางวัลร้านอาหารระดับสากล] จาก [นิตยสารต่างประเทศ] และ [รางวัลอาหารไทยระดับประเทศ] 2024 ร้านเดียวในไทย"> |
|
|
|
<!-- /contact.php --> |
|
<title>ติดต่อและเส้นทาง | [ชื่อลูกค้า] [จังหวัด]</title> |
|
<meta name="description" content="ที่อยู่ เส้นทาง เวลาเปิดปิด และวิธีสำรองที่นั่งของ [ชื่อลูกค้า] [ชื่อลูกค้ารายอื่น] [อำเภอ/ตำบล] [จังหวัด] เปิดทุกวัน 11.00-21.00 น. โทร [เบอร์โทรลูกค้า]"> |
|
|
|
<!-- /gallery.php --> |
|
<title>แกลเลอรี่ภาพร้านและอาหาร | [ชื่อลูกค้า]</title> |
|
<!-- [หน้าวิดีโอ] --> |
|
<title>วิดีโอเบื้องหลังและรีวิว | [ชื่อลูกค้า]</title> |
|
<!-- /blog/ --> |
|
<title>บทความ เรื่องเล่าจาก[อำเภอ/ตำบล] | [ชื่อลูกค้า]</title> |
|
<!-- บทความรายบท เช่น /blog/2/ภาชนะ/ --> |
|
<title>ภาชนะดินเผาทำมือจาก[ตำบล] | [ชื่อลูกค้า]</title> |
|
|
|
# verify ว่าไม่มี title ซ้ำแล้ว — ต้องได้ 15 บรรทัดที่ไม่ซ้ำกัน |
|
for u in "" about.php menu.php awards.php gallery.php video.php contact.php blog/; do |
|
curl -s "https://[โดเมนลูกค้า]/$u" | grep -o "<title>[^<]*</title>" |
|
done | sort | uniq -c | sort -rn |
|
ผลที่คาดหวัง แต่ละหน้ามีตัวตนของตัวเองในผลการค้นหา · AI แยกออกว่าหน้าไหนตอบคำถามอะไร · CTR จากผลการค้นหาสูงขึ้น |
Score Impact +3.2 pts |
เวลาประมาณ 1–1.5 ชั่วโมง |
|
#007 |
P1 |
ใส่ canonical tag ทุกหน้า |
|
Dimension |
Crawlability |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า |
|
ส่วนที่แก้ |
<link rel='canonical'> ใน <head> |
|
ปัญหา |
ตรวจครบทั้ง 15 หน้าไม่พบ canonical tag สักหน้าเดียว แม้การจัดการโดเมนจะถูกต้องแล้ว (http เด้ง https และ www เด้ง apex) แต่การไม่มี canonical ทำให้เสียคะแนน Indexability ไป 30 จาก 80 และเปิดช่องให้เกิด duplicate จาก URL ที่มี query string เช่น [หน้าวิดีโอ]?sort=desc กับ [หน้าวิดีโอ]?sort=asc ที่เนื้อหาเกือบเหมือนกัน |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- หน้าแรก (ทั้ง / และ /index.php ใช้ตัวเดียวกัน) --> |
|
<link rel="canonical" href="https://[โดเมนลูกค้า]/" /> |
|
|
|
<!-- หน้าอื่น --> |
|
<link rel="canonical" href="https://[โดเมนลูกค้า]/menu.php" /> |
|
<link rel="canonical" href="https://[โดเมนลูกค้า]/about.php" /> |
|
<link rel="canonical" href="https://[โดเมนลูกค้า]/contact.php" /> |
|
|
|
<!-- [หน้าวิดีโอ]?sort=desc และ ?sort=asc ทั้งคู่ชี้ไปตัวเปล่า --> |
|
<link rel="canonical" href="https://[โดเมนลูกค้า][หน้าวิดีโอ]" /> |
|
|
|
<!-- แบบ dynamic ใน PHP --> |
|
<?php |
|
$canonical = 'https://[โดเมนลูกค้า]' |
|
. strtok($_SERVER['REQUEST_URI'], '?'); |
|
if ($canonical === 'https://[โดเมนลูกค้า]/index.php') |
|
$canonical = 'https://[โดเมนลูกค้า]/'; |
|
?> |
|
<link rel="canonical" href="<?= htmlspecialchars($canonical) ?>" /> |
|
|
|
# verify |
|
for u in "" index.php menu.php about.php contact.php; do |
|
printf '%-12s ' "$u"; curl -s "https://[โดเมนลูกค้า]/$u" | grep -o 'rel="canonical" href="[^"]*"' |
|
done |
|
ผลที่คาดหวัง Google รวมสัญญาณของแต่ละหน้าไว้ที่ URL เดียว ไม่กระจายไปตาม query string |
Score Impact +1.1 pts |
เวลาประมาณ 45 นาที |
|
#008 |
P1 |
ใส่ OG tag และ twitter:card ทุกหน้า |
|
Dimension |
Content |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า |
|
ส่วนที่แก้ |
<meta property='og:*'> และ <meta name='twitter:*'> ใน <head> |
|
ปัญหา |
ทั้งเว็บไม่มี og:title, og:description, og:image, og:url และไม่มี twitter:card เลยสักตัว ผลตรงที่เห็นได้ทันทีคือเมื่อแชร์ลิงก์ร้านลง LINE, Facebook หรือ Messenger จะไม่มีรูปและไม่มีคำบรรยายขึ้นให้เลย มีแต่ URL เปล่าๆ ซึ่งกระทบพฤติกรรมลูกค้าจริงของร้านนี้โดยตรง เพราะช่องทางหลักที่ลูกค้าใช้ส่งต่อร้านให้เพื่อนคือ LINE |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- ใส่ทุกหน้า เปลี่ยนเฉพาะ title/description/url ตามหน้า --> |
|
<meta property="og:type" content="restaurant" /> |
|
<meta property="og:site_name" content="[ชื่อลูกค้า]" /> |
|
<meta property="og:locale" content="th_TH" /> |
|
<meta property="og:url" content="https://[โดเมนลูกค้า]/" /> |
|
<meta property="og:title" content="[ชื่อลูกค้า] | ร้านอาหารไทยพื้นบ้านริมน้ำ [จังหวัด]" /> |
|
<meta property="og:description" content="ร้านอาหารไทยพื้นบ้า[ชื่อลูกค้ารายอื่น] ชุมชน[อำเภอ/ตำบล] [จังหวัด] ในอาคารบล็อกแก้วรางวัล [นิตยสารต่างประเทศ] เปิดทุกวัน 11.00-21.00 น." /> |
|
<meta property="og:image" content="https://[โดเมนลูกค้า]/og-cover-1200x630.jpg" /> |
|
<meta property="og:image:width" content="1200" /> |
|
<meta property="og:image:height" content="630" /> |
|
<meta property="og:image:alt" content="อาคารบล็อกแก้[ชื่อลูกค้ารายอื่น] [ชื่อลูกค้า] ยามพลบค่ำ" /> |
|
|
|
<meta name="twitter:card" content="summary_large_image" /> |
|
<meta name="twitter:title" content="[ชื่อลูกค้า] | ร้านอาหารไทยพื้นบ้านริมน้ำ [จังหวัด]" /> |
|
<meta name="twitter:description" content="ร้านอาหารไทยพื้นบ้า[ชื่อลูกค้ารายอื่น] ชุมชน[อำเภอ/ตำบล] [จังหวัด]" /> |
|
<meta name="twitter:image" content="https://[โดเมนลูกค้า]/og-cover-1200x630.jpg" /> |
|
|
|
# verify |
|
curl -s https://[โดเมนลูกค้า]/ | grep -o 'property="og:[^"]*"' | sort |
|
ผลที่คาดหวัง แชร์ลิงก์ลง LINE, Facebook, Messenger แล้วขึ้นรูปและคำบรรยายทันที · ปลดค่าปรับ og:image −5 |
Score Impact +2.6 pts |
เวลาประมาณ 1 ชั่วโมง (รวมทำรูป og:image) |
|
#009 |
P1 |
ใส่ H1 ให้หน้าแรก และแก้ H1 ซ้อน 2 ตัวบนหน้าวิดีโอ |
|
Dimension |
Content |
|
หน้าที่แก้ |
https://[โดเมนลูกค้า]/ (หน้าแรก) · https://[โดเมนลูกค้า][หน้าวิดีโอ] |
|
ส่วนที่แก้ |
หน้าแรก: <div class='hi_p1'> และ <div class='hi_p2'> · หน้าวิดีโอ: <h1 class='size32 size24-sm size18-xs'> |
|
ปัญหา |
นับ h1 ถึง h6 บนหน้าแรกได้ศูนย์ทั้งที่มีเนื้อหาบรรยายร้านยาว 3 ย่อหน้า AI จึงไม่มีสัญญาณโครงสร้างเลยว่าอะไรคือหัวข้อของหน้า ทำให้โดนหัก 15 คะแนน ส่วนหน้า [หน้าวิดีโอ] มี H1 สองตัวคือ วิดีโอ และ Video Clip ซึ่งขัดกันเอง ทำให้โดนหักอีก 10 คะแนน รวมสองจุดนี้กินไป 25 คะแนนของ Content Understandability |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- หน้าแรก — เพิ่ม H1 (ตอนนี้ไม่มี heading เลยแม้แต่ตัวเดียว) --> |
|
<div class="container"> |
|
<div class="home_intro"> |
|
<h1>[ชื่อลูกค้า] — ร้านอาหารไทยพื้นบ้า[ชื่อลูกค้ารายอื่น] [จังหวัด]</h1> |
|
<div class="hi_text"> |
|
<div class="hi_p1"> |
|
<p>" เป็นมากกว่าร้านอาหาร</p> |
|
<p>เปรียบเสมือนคัมภีร์ ที่ยังมีลมหายใจ "</p> |
|
</div> |
|
<div class="hi_p2"> |
|
<!-- เดิม: <p><b>[ชื่อลูกค้า]<br>" [ชื่อลูกค้า] [จังหวัด] "</b></p> --> |
|
<h2>[ชื่อลูกค้า] " [ชื่อลูกค้า] [จังหวัด] "</h2> |
|
... |
|
|
|
<!-- [หน้าวิดีโอ] — เดิมมี H1 สองตัว --> |
|
<!-- ตัวที่ 1 เก็บไว้ --> |
|
<h1>วิดีโอ</h1> |
|
<!-- ตัวที่ 2 เปลี่ยนเป็น H2 --> |
|
<!-- ผิด --> <h1 class="size32 size24-sm size18-xs" style="color:#aaa436">Video Clip</h1> |
|
<!-- ถูก --> <h2 class="size32 size24-sm size18-xs" style="color:#aaa436">Video Clip</h2> |
|
|
|
# verify — หน้าแรกต้องได้ h1=1 · video.php ต้องได้ h1=1 |
|
for u in "" video.php; do |
|
printf '%-12s h1=' "$u" |
|
curl -s "https://[โดเมนลูกค้า]/$u" | grep -o "<h1" | wc -l |
|
done |
|
ผลที่คาดหวัง AI อ่านโครงสร้างหน้าออก · ปลดค่าปรับรวม 25 คะแนนใน Content Understandability |
Score Impact +5.0 pts |
เวลาประมาณ 45 นาที |
|
#010 |
P1 |
ประกาศที่อยู่และอีเมลบนหน้าติดต่อและ footer |
|
Dimension |
AI Overview / E-E-A-T |
|
หน้าที่แก้ |
https://[โดเมนลูกค้า]/contact.php · footer ของทุกหน้า |
|
ส่วนที่แก้ |
<div class='contact-info'> บนหน้าติดต่อ และ <div class='footer'> ในทุกหน้า |
|
ปัญหา |
หน้าติดต่อมีเบอร์โทร [เบอร์โทรลูกค้า] มี LINE มีแผนที่ฝัง และมีคำบอกทาง แต่ไม่มีที่อยู่แบบไปรษณีย์เป็นข้อความเลย และไม่มีอีเมล ผลที่ตามมาวัดได้จริง คือ directory ภายนอกแต่ละเจ้ากรอกที่อยู่กันคนละแบบจนอำเภอไม่ตรงกัน TripAdvisor ระบุ [อำเภอ] · [ลิงก์ภายนอก] ระบุ [อำเภอ] · [ไดเรกทอรีภายนอก] ระบุ [ตำบล] · [ไดเรกทอรีภายนอก] ระบุแค่ [บ้านเลขที่] [จังหวัด] ต้นเหตุคือเว็บของแบรนด์เองไม่เคยประกาศที่อยู่ที่ถูกต้องไว้ให้ยึด |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- /contact.php — เพิ่มก่อนบล็อกคำบอกทางเดิม --> |
|
<div class="contact-info"> |
|
<h2>ที่อยู่</h2> |
|
<address> |
|
[ชื่อลูกค้า] ([ชื่อลูกค้า] [จังหวัด])<br> |
|
[เลขที่ — ยืนยันกับลูกค้า] หมู่ [x] ชุมชน[อำเภอ/ตำบล]<br> |
|
ตำบล[ยืนยัน] อำเภอ[ยืนยัน] จังหวัด[จังหวัด] [รหัสไปรษณีย์]<br> |
|
โทร <a href="tel:[เบอร์โทรลูกค้า]">[เบอร์โทรลูกค้า]</a><br> |
|
อีเมล <a href="mailto:[อีเมลลูกค้า]">[อีเมลลูกค้า]</a><br> |
|
LINE <a href="https://[LINE ลูกค้า]">[บัญชีโซเชียลลูกค้า]</a> |
|
</address> |
|
<p>พิกัด [พิกัด]</p> |
|
</div> |
|
|
|
<!-- footer ทุกหน้า — เพิ่มบรรทัด NAP --> |
|
<div class="footer"> |
|
<p>[ชื่อลูกค้า] · ชุมชน[อำเภอ/ตำบล] จ.[จังหวัด] [รหัสไปรษณีย์] · |
|
<a href="tel:[เบอร์โทรลูกค้า]">[เบอร์โทรลูกค้า]</a> · เปิดทุกวัน 11.00-21.00 น.</p> |
|
<a target="_blank" href="https://[โดเมนภายนอก]" rel="noreferrer noopener"> |
|
© [ชื่อลูกค้า] 2022</a> |
|
</div> |
|
ผลที่คาดหวัง AI มีที่อยู่ฉบับทางการให้ยึด · directory ที่กรอกผิดสามารถถูกแก้ให้ตรงกันได้ · ปลดทางไปสู่การยกเลิกค่าปรับ NAP 10 คะแนน |
Score Impact +2.4 pts (E-E-A-T contact ครบ 0 → 15) และเป็นเงื่อนไขของ OS-1 |
เวลาประมาณ 45 นาที (หลังได้ข้อมูลยืนยันจากลูกค้า) |
|
#011 |
P1 |
ถอด translate='no' และ class='notranslate' ออกจาก <html> |
|
Dimension |
Content / Crawlability |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า |
|
ส่วนที่แก้ |
<html lang='th' class='notranslate' translate='no'> |
|
ปัญหา |
ทุกหน้าประกาศ <html lang='th' class='notranslate' translate='no'> ซึ่งเป็นคำสั่งบอกเบราว์เซอร์และ Google Translate ว่าห้ามแปลหน้านี้ เมื่อรวมกับการที่เว็บภาษาอังกฤษไม่มีอยู่จริงตาม ticket #003 เท่ากับปิดทางเข้าถึงเนื้อหาสำหรับผู้อ่านต่างชาติทั้งสองทางพร้อมกัน คือไม่มีฉบับแปลของตัวเอง และห้ามเครื่องมือแปลให้ด้วย สำหรับร้านในเมืองมรดกโลก UNESCO ที่นักท่องเที่ยวต่างชาติเป็นตลาดหลัก นี่คือการตัดขาดตลาดโดยไม่ตั้งใจ |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- ผิด (ปัจจุบัน) --> |
|
<html lang="th" class="notranslate" translate="no"> |
|
|
|
<!-- ถูก --> |
|
<html lang="th"> |
|
|
|
<!-- ถ้าจำเป็นต้องกันชื่อแบรนด์ไม่ให้ถูกแปล ให้ทำเฉพาะจุด --> |
|
<h2><span class="notranslate" translate="no">[ชื่อลูกค้า]</span> " [ชื่อลูกค้า] [จังหวัด] "</h2> |
|
|
|
# verify — ต้องไม่เจอ notranslate ที่ระดับ <html> แล้ว |
|
curl -s https://[โดเมนลูกค้า]/ | grep -o "<html[^>]*>" |
|
# ผลที่ถูกต้อง: <html lang="th"> |
|
ผลที่คาดหวัง ผู้อ่านต่างชาติแปลหน้าอ่านเองได้ผ่าน Chrome หรือ Safari ระหว่างรอเว็บ EN ฉบับจริง |
Score Impact +1.2 pts |
เวลาประมาณ 20 นาที |
4 P2 — Medium Priority Tickets ปรับปรุงภายใน 1 เดือน
|
#012 |
P2 |
เพิ่ม alt text ให้รูปที่ขาดหรือกว้างเกินไป 79 จุด (28 ไฟล์ที่ไม่ซ้ำกัน) |
|
Dimension |
Content |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า — ดูตาราง alt เต็มในหัวข้อ 7 |
|
ส่วนที่แก้ |
attribute alt ของ <img> ทุกตัว |
|
ปัญหา |
นับ tag <img> ทั้งหมด 203 ตัวจาก 15 หน้าที่ crawl ได้ แยกเป็น alt='' บนรูปเนื้อหา 59 ตัว และ alt ที่กว้างเกินไปจนไม่มีความหมาย 20 ตัว ไฟล์ที่ต้องแก้จริงมี 28 ไฟล์ที่ไม่ซ้ำกัน ตัวที่หนักที่สุดคือโลโก้ /svg/aa-color.svg ที่ปรากฏ 45 ครั้งทั่วเว็บโดยตั้ง alt='' ทุกครั้ง แปลว่าสัญลักษณ์แบรนด์ที่ปรากฏถี่ที่สุดบนเว็บ AI มองไม่เห็นเลย รองลงมาคือ thumbnail วิดีโอ 6 ตัวที่ตั้ง alt='Youtube' เหมือนกันหมด ซึ่งบอกแค่ว่ามาจากแพลตฟอร์มไหน ไม่ได้บอกว่าคลิปเรื่องอะไร |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- โลโก้ — แก้ที่ template กลางครั้งเดียว มีผล 45 จุด --> |
|
<!-- ผิด --> <img src="/svg/aa-color.svg" alt="" class="ftlogo"> |
|
<!-- ถูก --> <img src="/svg/aa-color.svg" alt="โลโก้ [ชื่อลูกค้า] [ชื่อลูกค้า] [จังหวัด]" class="ftlogo"> |
|
|
|
<!-- รูปรางวัล — มูลค่าสูงสุดของทั้งเว็บ --> |
|
<img src="imgs/[ไฟล์รูปลูกค้า]" |
|
alt="ใบประกาศ [รางวัลอาหารไทยระดับประเทศ] มอบให้ [ชื่อลูกค้า] [จังหวัด] โดยกรมพัฒนาธุรกิจการค้า กันยายน 2024"> |
|
|
|
<img src="imgs/award-rv2.jpg" |
|
alt="หน้ารางวัล [รางวัลร้านอาหารระดับสากล] ในนิตยสาร [นิตยสารต่างประเทศ] ระบุ [ชื่อลูกค้า] โดย [สตูดิโอออกแบบ]"> |
|
|
|
<!-- รูปที่ตอบคำถามลูกค้าได้ตรงๆ --> |
|
<img src="ab-06.jpg" |
|
alt="ล่องเรือชมโบราณสถานอยุธย[ชื่อลูกค้ารายอื่น] เรือของ [ชื่อลูกค้า]"> |
|
|
|
<img src="thai-dance.jpg" |
|
alt="การแสดงนาฏศิลป์ไทยของเด็กนักเรียนทุกเย็นวันเสาร์อาทิตย์ ริมแม่น้ำ[จังหวัด]"> |
|
|
|
<!-- thumbnail วิดีโอ — เดิม alt="Youtube" ทั้ง 6 ตัว ให้ใช้ชื่อคลิปจริง --> |
|
<!-- ผิด --> <img src="https://[โฮสต์รูปภายนอก]" alt="Youtube"> |
|
<!-- ถูก --> <img src="https://[โฮสต์รูปภายนอก]" |
|
alt="Time-Lapse การก่อสร้างอาคารบล็อกแก้วของ [ชื่อลูกค้า]"> |
|
|
|
<!-- ไอคอน hamburger ที่เป็นของตกแต่ง ใส่ alt="" ถูกแล้ว ไม่ต้องแก้ --> |
|
<img src="/svg/nav.svg" alt="" class="smnav"> |
|
ผลที่คาดหวัง Google Images เก็บรูปได้พร้อมบริบท · AI มีหลักฐานข้อความสำหรับตอบคำถามอย่างพาสัตว์เลี้ยงได้ไหม มีการแสดงวันไหน ล่องเรือยังไง |
Score Impact +3.4 pts |
เวลาประมาณ 2–3 ชั่วโมง |
|
#013 |
P2 |
แก้หน้าแกลเลอรี่ให้ใช้ <img> จริงแทน CSS background |
|
Dimension |
Content / Technical |
|
หน้าที่แก้ |
https://[โดเมนลูกค้า]/gallery.php |
|
ส่วนที่แก้ |
<div class='gl-item'>Image39.jpg</div> ทั้ง 21 กล่อง และ script jQuery ท้ายหน้า |
|
ปัญหา |
หน้าแกลเลอรี่ไม่มี tag <img> สำหรับรูปแกลเลอรี่เลยแม้แต่ตัวเดียว โครงสร้างจริงคือใส่ชื่อไฟล์เป็นข้อความในกล่อง div แล้วใช้ jQuery อ่านชื่อไฟล์จากข้อความนั้น เอาไปตั้งเป็น CSS background-image แล้วลบข้อความทิ้ง ผลคือถ้า JS ไม่ทำงาน ผู้ใช้และ crawler จะเห็นชื่อไฟล์ 21 บรรทัดเรียงกันเป็นเนื้อหาหน้า แต่ถ้า JS ทำงาน รูปจะกลายเป็น background ที่ใส่ alt ไม่ได้และ Google Images เก็บไม่ได้ ทั้งสองทางเว็บไม่ได้อะไรจากรูป 21 รูปนี้เลย ซ้ำยังได้ข้อความขยะเพิ่มมาอีก 21 บรรทัด |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- ผิด (ปัจจุบัน) — ชื่อไฟล์เป็นข้อความในหน้า --> |
|
<div class="gl-item">Image39.jpg</div> |
|
|
|
<script> |
|
$(function() { |
|
$('.gl-item').each(function () { |
|
if ($(this).text() != '') { |
|
var iu = $(this).text(); |
|
$(this).css('background-image','url(gallery/'+iu+')'); |
|
$(this).html(''); |
|
} |
|
}); |
|
}); |
|
</script> |
|
|
|
<!-- ถูก — <img> จริง ลบ script ออกทั้งหมด --> |
|
<div class="gl-item"> |
|
<img src="gallery/Image39.jpg" |
|
alt="[เขียนตามตารางหัวข้อ 7]" |
|
width="1200" height="1200" loading="lazy"> |
|
</div> |
|
|
|
<div class="gl-item see-more"> |
|
<a href="https://[LINE ลูกค้า]" target="_blank" rel="nofollow"> |
|
<img src="gallery/Image18-2.jpg" alt="[เขียนตามตารางหัวข้อ 7]" |
|
width="1200" height="1200" loading="lazy"> |
|
<span class="see-m-btn">See more</span> |
|
</a> |
|
</div> |
|
|
|
/* CSS — แทนที่กฎเดิม */ |
|
/* เดิม: .gl-item {padding-top:100%;background-size:cover;...} */ |
|
.gl-item { position: relative; width: 100%; aspect-ratio: 1/1; overflow: hidden; |
|
margin: 0 auto; transition: .5s all; cursor: pointer; } |
|
.gl-item img { width: 100%; height: 100%; object-fit: cover; display: block; } |
|
.gl-item:hover { filter: contrast(128%) brightness(128%); } |
|
.gl-item .see-m-btn { position: absolute; inset: 0; display: flex; |
|
align-items: center; justify-content: center; } |
|
|
|
# verify — ต้องได้ 21 ไม่ใช่ 0 |
|
curl -s https://[โดเมนลูกค้า]/gallery.php | grep -c 'gallery/Image' |
|
ผลที่คาดหวัง รูป 21 รูปกลับมา index ได้ใน Google Images พร้อม alt · หน้าไม่มีข้อความขยะชื่อไฟล์อีกต่อไป · หน้าใช้งานได้แม้ JS ไม่ทำงาน |
Score Impact +2.8 pts |
เวลาประมาณ 2 ชั่วโมง |
|
#014 |
P2 |
เพิ่ม BreadcrumbList และ WebSite schema |
|
Dimension |
AI Overview |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า |
|
ส่วนที่แก้ |
<script type='application/ld+json'> ใน <head> |
|
ปัญหา |
Tier 1 ของ Schema Eligibility ยังขาด BreadcrumbList 10 คะแนน และ WebSite 5 คะแนน ซึ่งเป็นสองตัวที่ทำง่ายที่สุดในทั้งหมด ใช้เวลารวมไม่ถึงหนึ่งชั่วโมงแต่ได้ 15 คะแนนใน Tier 1 |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- WebSite — ใส่ทุกหน้า --> |
|
<script type="application/ld+json"> |
|
{ |
|
"@context": "https://schema.org", |
|
"@type": "WebSite", |
|
"@id": "https://[โดเมนลูกค้า]/#website", |
|
"name": "[ชื่อลูกค้า]", |
|
"alternateName": "[ชื่อลูกค้า] [จังหวัด]", |
|
"url": "https://[โดเมนลูกค้า]/", |
|
"inLanguage": "th-TH", |
|
"publisher": { "@id": "https://[โดเมนลูกค้า]/#restaurant" } |
|
} |
|
</script> |
|
|
|
<!-- BreadcrumbList — ตัวอย่างหน้าเมนู --> |
|
<script type="application/ld+json"> |
|
{ |
|
"@context": "https://schema.org", |
|
"@type": "BreadcrumbList", |
|
"itemListElement": [ |
|
{ "@type": "ListItem", "position": 1, "name": "หน้าแรก", |
|
"item": "https://[โดเมนลูกค้า]/" }, |
|
{ "@type": "ListItem", "position": 2, "name": "เมนู", |
|
"item": "https://[โดเมนลูกค้า]/menu.php" } |
|
] |
|
} |
|
</script> |
|
|
|
<!-- BreadcrumbList — ตัวอย่างบทความ 3 ระดับ --> |
|
<script type="application/ld+json"> |
|
{ |
|
"@context": "https://schema.org", |
|
"@type": "BreadcrumbList", |
|
"itemListElement": [ |
|
{ "@type": "ListItem", "position": 1, "name": "หน้าแรก", |
|
"item": "https://[โดเมนลูกค้า]/" }, |
|
{ "@type": "ListItem", "position": 2, "name": "บทความ", |
|
"item": "https://[โดเมนลูกค้า]/blog/" }, |
|
{ "@type": "ListItem", "position": 3, "name": "ภาชนะ" } |
|
] |
|
} |
|
</script> |
|
ผลที่คาดหวัง SERP แสดง breadcrumb แทน URL ดิบ · AI เข้าใจลำดับชั้นของเว็บ |
Score Impact +1.9 pts (Tier 1 +15) |
เวลาประมาณ 1 ชั่วโมง |
|
#015 |
P2 |
เพิ่ม FAQ จริงบนหน้าเว็บพร้อม FAQPage schema |
|
Dimension |
AI Overview |
|
หน้าที่แก้ |
https://[โดเมนลูกค้า]/contact.php หรือหน้าใหม่ /faq.php |
|
ส่วนที่แก้ |
เนื้อหาใหม่ + <script type='application/ld+json'> |
|
ปัญหา |
ทั้งเว็บไม่มี FAQ อยู่จริงเลยสักชุด และไม่มี heading ที่เป็นรูปคำถามสักตัว ทำให้ Snippet Readiness เสียคะแนนสองข้อรวด คือไม่มีย่อหน้าตอบตรงคำถาม 35 คะแนน และไม่มี heading รูปคำถาม 25 คะแนน คำถามที่ใส่ในโค้ดด้านล่างไม่ได้คิดขึ้นเอง แต่มาจากสิ่งที่ค้นเจอจริงว่าคนถามระหว่างทำ audit |
วิธีแก้
Code / คำสั่งที่ใช้
|
<h2>[ชื่อลูกค้า] ราคาเท่าไร</h2> |
|
<p>สำรับอาหารไทยพื้นบ้านเริ่มต้นที่ 2,400 บาท++ สำหรับสำรับรองท้อง 2 ท่าน |
|
สำรับป้าขันทองสำหรับ 1 ท่าน 2,900 บาท++ และสำรับป้าอี้สำหรับ 1 ท่าน 3,300 บาท++ |
|
อาหารตามสั่งเริ่มต้นจานละ 320 บาท ราคายังไม่รวม service charge |
|
ดูรายละเอียดทั้งหมดได้ที่หน้าเมนู</p> |
|
|
|
<h2>ต้องจองล่วงหน้าไหม</h2> |
|
<p>ต้องสำรองที่นั่งล่วงหน้าเท่านั้น โดยเฉพาะมื้อรองท้องช่วง 13.00 ถึง 16.00 น. |
|
สำรองที่นั่งได้ทางโทรศัพท์ [เบอร์โทรลูกค้า] หรือ LINE ของร้าน |
|
แนะนำให้จองล่วงหน้าอย่างน้อย 3 วันสำหรับวันเสาร์และอาทิตย์</p> |
|
|
|
<h2>ล่องเรือราคาเท่าไร จองอย่างไร</h2> |
|
<p>ล่องเรือย้อนรอยแม่น้ำประวัติศาสตร์ 3 สาย [ชื่อลูกค้ารายอื่น] แม่น้ำลพบุรี |
|
และแม่น้ำป่าสัก ราคา 3,500 บาท++ ต่อชั่วโมง รองรับสูงสุด 6 ท่านต่อรอบ |
|
มีรอบ 12.00 น. และ 15.00 น. สำรองล่วงหน้าทางโทรศัพท์หรือ LINE</p> |
|
|
|
<h2>มีการแสดงวันไหนบ้าง</h2> |
|
<p>มีการแสดงศิลปวัฒนธรรมไทยพื้นบ้านโดยเด็กนักเรียนในชุมชน ทุกเย็นวันเสาร์และอาทิตย์ |
|
ที่ลานไม้ริมน้ำหน้าตึกป้าเสงี่ยม สำหรับผู้มาเยือนที่สั่งอาหารตั้งแต่ 2 สำรับขึ้นไป |
|
หากต้องการชมในวันธรรมดาสามารถแจ้งทางร้านล่วงหน้าได้ โดยมีค่าบริการเพิ่มเติม</p> |
|
|
|
<h2>เดินทางจากกรุงเทพอย่างไร</h2> |
|
<p>ใช้[ถนนเลี่ยงเมือง][จังหวัด]-[จังหวัดใกล้เคียง] หรือ[ทางหลวง] ลงสะพาน[ชื่อลูกค้ารายอื่น] |
|
ฝั่งแม่น้ำ[ชื่อสถานที่] ร้านอยู่ซ้ายมือ ใช้เวลาจากกรุงเทพประมาณ 1 ชั่วโมง 30 นาที |
|
พิกัด [พิกัด] มีที่จอดรถในร้าน</p> |
|
|
|
<h2>เปิดกี่โมง</h2> |
|
<p>เปิดบริการทุกวัน มื้ออาหารเวลา 11.00 ถึง 21.00 น. |
|
และมื้อรองท้องเวลา 13.00 ถึง 16.00 น. ซึ่งต้องสำรองที่นั่งล่วงหน้าเท่านั้น</p> |
|
|
|
<!-- FAQPage schema — ข้อความต้องตรงกับด้านบนทุกตัวอักษร --> |
|
<script type="application/ld+json"> |
|
{ |
|
"@context": "https://schema.org", |
|
"@type": "FAQPage", |
|
"mainEntity": [ |
|
{ "@type": "Question", "name": "[ชื่อลูกค้า] ราคาเท่าไร", |
|
"acceptedAnswer": { "@type": "Answer", |
|
"text": "สำรับอาหารไทยพื้นบ้านเริ่มต้นที่ 2,400 บาท++ สำหรับสำรับรองท้อง 2 ท่าน สำรับป้าขันทองสำหรับ 1 ท่าน 2,900 บาท++ และสำรับป้าอี้สำหรับ 1 ท่าน 3,300 บาท++ อาหารตามสั่งเริ่มต้นจานละ 320 บาท ราคายังไม่รวม service charge" } }, |
|
{ "@type": "Question", "name": "ต้องจองล่วงหน้าไหม", |
|
"acceptedAnswer": { "@type": "Answer", |
|
"text": "ต้องสำรองที่นั่งล่วงหน้าเท่านั้น สำรองได้ทางโทรศัพท์ [เบอร์โทรลูกค้า] หรือ LINE ของร้าน แนะนำให้จองล่วงหน้าอย่างน้อย 3 วันสำหรับวันเสาร์และอาทิตย์" } } |
|
/* ใส่ให้ครบทั้ง 6 ข้อ */ |
|
] |
|
} |
|
</script> |
|
ผลที่คาดหวัง หน้ามีย่อหน้าที่ AI ดึงไปตอบได้ทันที · Tier 2 schema เพิ่มอีก 1 ตัว · Snippet Readiness ขยับขึ้นมาก |
Score Impact +4.2 pts |
เวลาประมาณ 2–3 ชั่วโมง |
|
#016 |
P2 |
ใส่ BlogPosting schema, author และ dateModified ให้บทความทั้ง 7 บท |
|
Dimension |
AI Overview |
|
หน้าที่แก้ |
/blog/1/ล่องเรือ/ · /blog/2/ภาชนะ/ · /blog/3/pet-friendly/ · /blog/4/สถาปัตยกรรม/ · /blog/5/ป้ายาย/ · /blog/6/ingredients/ · /blog/7/การแสดง/ |
|
ส่วนที่แก้ |
<head> ของ template บทความ + บล็อกเนื้อหา .blogs-fluid |
|
ปัญหา |
บทความทั้ง 7 บทไม่มี author ไม่มี BlogPosting schema และไม่มี dateModified ที่ไหนเลยบนเว็บ ซึ่งเป็นเหตุให้โดนหัก 10 คะแนนระดับมิติใน AI Overview Presence นอกจากนี้ทุกบทมีแค่ H1 ตัวเดียวแล้วไม่มี H2 หรือ H3 ต่อเลย ทำให้ AI ไม่มีจุดยึดว่าย่อหน้าไหนตอบเรื่องอะไร |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- ตัวอย่างบทความ /blog/2/ภาชนะ/ --> |
|
<script type="application/ld+json"> |
|
{ |
|
"@context": "https://schema.org", |
|
"@type": "BlogPosting", |
|
"headline": "ภาชนะดินเผาทำมือจาก[ตำบล]", |
|
"description": "ผู้มาเยือนที่มาเยือน [ชื่อลูกค้า] [จังหวัด] แทบทุกคนจะรู้ว่าถ้วยจานดินเผาที่นี่ไม่เท่ากันสักใบ", |
|
"image": "https://web.[โดเมนลูกค้า]/[พาธรูป]", |
|
"datePublished": "2024-11-21T14:15:00+07:00", |
|
"dateModified": "2026-08-16T00:00:00+07:00", |
|
"author": { "@type": "Organization", "name": "[ชื่อลูกค้า]", |
|
"url": "https://[โดเมนลูกค้า]/" }, |
|
"publisher": { "@id": "https://[โดเมนลูกค้า]/#restaurant" }, |
|
"mainEntityOfPage": { |
|
"@type": "WebPage", |
|
"@id": "https://[โดเมนลูกค้า]/blog/2/%E0%B8%A0%E0%B8%B2%E0%B8%8A%E0%B8%99%E0%B8%B0/" |
|
}, |
|
"inLanguage": "th-TH" |
|
} |
|
</script> |
|
|
|
<!-- แสดงวันที่บนหน้าจริงด้วย ไม่ใช่มีแค่ใน schema --> |
|
<p class="blog-meta"> |
|
เผยแพร่ <time datetime="2024-11-21">21 พฤศจิกายน 2567</time> · |
|
แก้ไขล่าสุด <time datetime="2026-08-16">16 สิงหาคม 2569</time> · |
|
โดย [ชื่อลูกค้า] |
|
</p> |
|
|
|
<!-- เพิ่ม H2 ในเนื้อหา --> |
|
<h2>[ชื่อบุคคล] ช่างปั้นดินเผาคนสุดท้ายแห่ง[ตำบล]</h2> |
|
<h2>ทำไมถ้วยจานที่นี่ไม่เท่ากันสักใบ</h2> |
|
|
|
/* แก้การจัดข้อความให้อ่านง่าย */ |
|
/* เดิม: <p style="text-align: center;"> ทุกย่อหน้า */ |
|
.blogs-fluid p { text-align: left; } |
|
ผลที่คาดหวัง ปลดค่าปรับ dateModified −10 · Tier 2 schema เพิ่มอีก 1 ตัว · บทความมีสิทธิ์ขึ้นเป็นแหล่งอ้างอิงใน AI Overview |
Score Impact +3.9 pts |
เวลาประมาณ 2 ชั่วโมง |
|
#017 |
P2 |
แก้ slug บทความ 2 บทที่ไม่ตรงกับเนื้อหา พร้อมตั้ง 301 |
|
Dimension |
Crawlability / Content |
|
หน้าที่แก้ |
/blog/3/pet-friendly/ · /blog/6/ingredients/ |
|
ส่วนที่แก้ |
URL slug และ rewrite rule ของ /blog/ |
|
ปัญหา |
slug ของบทความ 2 บทไม่ตรงกับเนื้อหาที่อยู่ข้างใน บทที่ 3 ใช้ slug ว่า pet-friendly แต่หัวข้อจริงคือ รางวัล และเนื้อหาพูดเรื่องการเป็นร้านอาหารพื้นบ้านของชุมชนชายขอบ ไม่มีเนื้อหาเรื่องสัตว์เลี้ยงเลย ส่วนบทที่ 6 ใช้ slug ว่า ingredients แต่หัวข้อจริงคือ อาหาร ผลคือ AI และ Google ได้รับสัญญาณขัดกันระหว่าง URL กับเนื้อหา ซึ่งลดความมั่นใจในการนำหน้าไปใช้อ้างอิง |
วิธีแก้
Code / คำสั่งที่ใช้
|
# ทางเลือก A — แก้ slug ให้ตรงเนื้อหา |
|
/blog/3/pet-friendly/ -> /blog/3/รางวัล/ (หรือ /blog/3/community-restaurant/) |
|
/blog/6/ingredients/ -> /blog/6/อาหาร/ (หรือ /blog/6/authentic-thai-food/) |
|
|
|
# ตั้ง 301 ใน .htaccess |
|
RewriteEngine On |
|
RewriteRule ^blog/3/pet-friendly/?$ /blog/3/community-restaurant/ [R=301,L] |
|
RewriteRule ^blog/6/ingredients/?$ /blog/6/authentic-thai-food/ [R=301,L] |
|
|
|
# ทางเลือก B (แนะนำถ้าร้านพาสัตว์เลี้ยงเข้าได้จริง) |
|
# เก็บ slug pet-friendly ไว้ แล้วเขียนบทความเรื่องพาสัตว์เลี้ยงมาร้านจริง |
|
# เพราะเป็นคำค้นที่มีปริมาณสูงและตอบคำถามที่คนถาม AI บ่อยมาก |
|
# ส่วนเนื้อหาเรื่องรางวัลปัจจุบันให้ย้ายไปเป็นบทความใหม่ |
|
|
|
# verify |
|
curl -sI https://[โดเมนลูกค้า]/blog/3/pet-friendly/ | head -1 # ต้องได้ 301 |
|
ผลที่คาดหวัง URL กับเนื้อหาส่งสัญญาณตรงกัน · ถ้าเลือกทางเลือก B จะได้หน้าที่ตอบคำถามที่คนค้นจริงเพิ่มมาหนึ่งหน้า |
Score Impact +0.9 pts (หรือมากกว่าถ้าเลือกทางเลือก B) |
เวลาประมาณ 1 ชั่วโมง (ทางเลือก A) · 3–4 ชั่วโมง (ทางเลือก B รวมเขียนบทความ) |
|
#018 |
P2 |
แก้ preload ของวิดีโอ 42.8 MB ลบรูป fallback ที่โหลดฟรี และลบ JS ที่ใส่ source ซ้ำ |
|
Dimension |
Technical |
|
หน้าที่แก้ |
https://[โดเมนลูกค้า]/ (หน้าแรก) |
|
ส่วนที่แก้ |
<video> ใน .container · <div class='hero_sim'><img src='hero_ab.jpg'> · script ท้ายหน้า |
|
ปัญหา |
ปัญหาสามชั้นในบล็อกเดียว ชั้นแรก ไฟล์ /mp4/about-preview.mp4 มีขนาด 44,863,739 ไบต์ หรือ 42.8 MB ถูกตั้ง autoplay ร่วมกับ preload='auto' บนจอตั้งแต่ 728px ขึ้นไป คะแนน Lighthouse ยังออกมาดีเพราะ lab test ตัดจบก่อนวิดีโอโหลดครบ แต่ผู้ใช้จริงจะถูกดูดดาต้าหลายสิบเมกะไบต์โดยไม่ได้ขอ ชั้นที่สอง มี <img src='hero_ab.jpg'> อยู่ภายใน <video> ตั้งใจให้เป็น fallback แต่เบราว์เซอร์ที่เล่นวิดีโอได้ยังโหลดรูปนี้อยู่ดี วัดได้ 47 KB บนมือถือที่ไม่เคยแสดงผลเลย ชั้นที่สาม script ท้ายหน้าใช้ jQuery append <source> ซ้ำเข้าไปในแท็ก <video> อีกรอบทั้งที่ HTML มี source ครบอยู่แล้ว |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- ผิด (ปัจจุบัน) --> |
|
<video ... autoplay loop controls muted playsinline preload="auto" ...> |
|
<source src=".../about-preview-sm.mp4" media="(max-width: 727px)"> |
|
<source src=".../about-preview.mp4" media="(min-width: 728px)"> |
|
<div class="hero_sim"><img src="hero_ab.jpg" alt=""></div> <!-- โหลดฟรี 197 KB --> |
|
</video> |
|
|
|
<script> |
|
$(function() { /* <-- ลบ block นี้ทิ้งทั้งก้อน source มีครบแล้วใน HTML */ |
|
if ($(window).width()>992) { |
|
$("video").append('<source src=".../about-preview.mp4" type="video/mp4">'); |
|
} else { |
|
$("video").append('<source src=".../about-preview-sm.mp4" type="video/mp4">'); |
|
} |
|
}); |
|
</script> |
|
|
|
<!-- ถูก --> |
|
<video width="1280" height="720" |
|
poster="https://[โดเมนลูกค้า]/mp4/poster.jpg" |
|
autoplay loop controls muted playsinline |
|
preload="metadata"> |
|
<source src="https://[โดเมนลูกค้า]/mp4/about-preview-sm.mp4" |
|
type="video/mp4" media="(max-width: 727px)"> |
|
<source src="https://[โดเมนลูกค้า]/mp4/about-preview.mp4" |
|
type="video/mp4" media="(min-width: 728px)"> |
|
</video> |
|
|
|
# บีบวิดีโอ 42.8 MB ให้เหลือประมาณ 8-10 MB |
|
ffmpeg -i about-preview.mp4 -vcodec libx264 -crf 28 -preset slow \ |
|
-vf "scale=1280:-2" -movflags +faststart -an about-preview-new.mp4 |
|
|
|
# ตรวจขนาดปัจจุบัน |
|
curl -sI https://[โดเมนลูกค้า]/mp4/about-preview.mp4 | grep -i content-length |
|
# ปัจจุบัน: 44863739 (42.8 MB) |
|
ผลที่คาดหวัง ผู้ใช้เดสก์ท็อปประหยัดดาต้าหลายสิบเมกะไบต์ต่อการเข้าเว็บหนึ่งครั้ง · LCP ฝั่งมือถือดีขึ้นจาก 7.4 วินาที |
Score Impact +0.8 pts (Technical) แต่ผลกับผู้ใช้จริงสูงกว่าที่คะแนนสะท้อน |
เวลาประมาณ 1–2 ชั่วโมง |
|
#019 |
P2 |
แก้นโยบายแคชและ cache-bust ที่เปลี่ยนทุกนาที |
|
Dimension |
Technical |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า — ระดับ header และการเรียก CSS |
|
ส่วนที่แก้ |
<link rel='stylesheet' href='/styles.css?nc=YYYYMMDDHHmm'> และ header Cache-Control จาก PHP session |
|
ปัญหา |
ทุกหน้าเรียก /styles.css?nc=YYYYMMDDHHmm ซึ่งเปลี่ยนค่าทุกนาที ประกอบกับ response header ตั้ง Cache-Control: no-store, no-cache, must-revalidate ซึ่งเป็นค่า default ของ PHP session ผลคือผู้ใช้ที่กลับมาเยี่ยมเว็บซ้ำต้องโหลดใหม่ทั้งหมดทุกครั้ง แม้ไฟล์จะไม่ได้เปลี่ยนเลยก็ตาม จุดที่ต้องเน้นคือเซิร์ฟเวอร์เร็วมาก TTFB วัดได้เพียง 6 มิลลิวินาที ปัญหาจึงอยู่ที่นโยบายแคชกับขนาดไฟล์ ไม่ใช่ที่ตัวเซิร์ฟเวอร์ |
วิธีแก้
Code / คำสั่งที่ใช้
|
<?php |
|
// ผิด (ปัจจุบัน) — เปลี่ยนทุกนาที |
|
// <link rel="stylesheet" href="/styles.css?nc=<?= date('YmdHi') ?>"> |
|
|
|
// ถูก — เปลี่ยนเมื่อไฟล์ถูกแก้จริงเท่านั้น |
|
$cssVer = @filemtime($_SERVER['DOCUMENT_ROOT'] . '/styles.css') ?: '1'; |
|
?> |
|
<link rel="stylesheet" href="/styles.css?v=<?= $cssVer ?>"> |
|
|
|
<?php |
|
// แก้ header no-store ที่มาจาก PHP session |
|
// ใส่ก่อน session_start() ทุกครั้ง |
|
session_cache_limiter('public'); |
|
session_cache_expire(180); |
|
session_start(); |
|
// ถ้าหน้านั้นไม่ได้ใช้ session เลย ให้ลบ session_start() ออกไปเลยจะดีที่สุด |
|
?> |
|
|
|
# .htaccess — แคช static asset ยาว 1 ปี |
|
<IfModule mod_expires.c> |
|
ExpiresActive On |
|
ExpiresByType text/css "access plus 1 year" |
|
ExpiresByType application/javascript "access plus 1 year" |
|
ExpiresByType image/jpeg "access plus 1 year" |
|
ExpiresByType image/png "access plus 1 year" |
|
ExpiresByType image/webp "access plus 1 year" |
|
ExpiresByType image/svg+xml "access plus 1 year" |
|
ExpiresByType video/mp4 "access plus 1 year" |
|
</IfModule> |
|
|
|
<FilesMatch "\.(css|js|jpg|jpeg|png|webp|svg|mp4)$"> |
|
Header set Cache-Control "public, max-age=31536000, immutable" |
|
</FilesMatch> |
|
|
|
# verify — ต้องไม่เห็น no-store แล้ว |
|
curl -sI https://[โดเมนลูกค้า]/ | grep -i cache-control |
|
ผลที่คาดหวัง ผู้ใช้ที่กลับมาเยี่ยมซ้ำโหลดหน้าได้เร็วขึ้นมาก · ลดภาระ bandwidth ของเซิร์ฟเวอร์ |
Score Impact +0.6 pts |
เวลาประมาณ 1 ชั่วโมง |
|
#020 |
P2 |
ใส่ noindex ให้หน้า placeholder ของ subdomain web.[โดเมนลูกค้า] |
|
Dimension |
Crawlability |
|
หน้าที่แก้ |
https://web.[โดเมนลูกค้า]/ |
|
ส่วนที่แก้ |
robots.txt หรือ header X-Robots-Tag ที่ subdomain |
|
ปัญหา |
subdomain นี้ตอบ HTTP 200 เป็นหน้า Default page ของ Hostinger โดยไม่มี noindex และเป็นที่เก็บรูปของ CMS หลังบ้านทั้งหมดใน path /ul/ และ /mce/ หน้า placeholder ที่ index ได้อาจไปแย่งสัญญาณกับโดเมนหลักและทำให้ผลการค้นหาชื่อแบรนด์ขึ้นหน้าเปล่าที่ไม่มีประโยชน์ |
วิธีแก้
Code / คำสั่งที่ใช้
|
# .htaccess ที่ document root ของ web.[โดเมนลูกค้า] |
|
# noindex เฉพาะหน้า HTML ไม่แตะไฟล์รูป |
|
<FilesMatch "\.(html|htm|php)$"> |
|
Header set X-Robots-Tag "noindex, nofollow" |
|
</FilesMatch> |
|
|
|
# robots.txt ของ subdomain — เปิดให้ crawler เก็บรูปได้ |
|
User-agent: * |
|
Allow: /ul/ |
|
Allow: /mce/ |
|
Disallow: /index.html |
|
|
|
# verify |
|
curl -sI https://web.[โดเมนลูกค้า]/ | grep -i x-robots-tag |
|
curl -sI https://web.[โดเมนลูกค้า]/[พาธรูป] | head -1 # ต้องยังได้ 200 |
|
ผลที่คาดหวัง หน้า placeholder หายจากผลการค้นหา · รูปบทความยังถูกเก็บใน Google Images ได้ตามปกติ |
Score Impact +0.4 pts |
เวลาประมาณ 30 นาที |
5 P3 — Low Priority Tickets งานเดือนที่ 2–3
|
#021 |
P3 |
เพิ่มลิงก์ YouTube ใน footer และตัดสินใจเรื่อง Instagram สองบัญชี |
|
Dimension |
AI Citation |
|
หน้าที่แก้ |
footer และ nav ทั้ง 3 ชุดในทุกหน้า |
|
ส่วนที่แก้ |
<div class='sns'> ในทุกหน้า |
|
ปัญหา |
แบรนด์มีช่อง YouTube [บัญชีโซเชียลลูกค้า] อยู่จริงและหน้า [หน้าวิดีโอ] ก็ฝังวิดีโอจากช่องนี้ถึง 6 คลิป แต่แถบ social ที่ footer มีแค่ Instagram, Facebook และ LINE ไม่มี YouTube เลย ทำให้เสียสะพานเชื่อม entity ไปหนึ่งเส้นโดยไม่จำเป็น ประเด็นที่สองคือค้นเจอ Instagram สองบัญชีคือ [บัญชีโซเชียลลูกค้า] ซึ่งมี 2,807 ผู้ติดตามและเป็นตัวที่เว็บลิงก์ไป กับ [บัญชีโซเชียลลูกค้า] อีกบัญชี บัญชีซ้ำทำให้ AI ผูก entity ได้ไม่แน่นอน |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- เพิ่มใน .sns ทุกจุด (มี 2 จุดต่อหน้า) --> |
|
<div class="sns"> |
|
<a target="_blank" href="https://instagram.com/[ชื่อลูกค้า]"> |
|
<img src="/svg/ig.svg" alt="Instagram ของ [ชื่อลูกค้า]"></a> |
|
<a target="_blank" href="https://www.facebook.com/[ชื่อลูกค้า]/"> |
|
<img src="/svg/fb.svg" alt="Facebook ของ [ชื่อลูกค้า]"></a> |
|
<a target="_blank" href="https://www.youtube.com/[บัญชีโซเชียลลูกค้า]"> |
|
<img src="/svg/yt.svg" alt="ช่อง YouTube ของ [ชื่อลูกค้า]"></a> |
|
<a target="_blank" href="https://[LINE ลูกค้า]"> |
|
<img src="/svg/line.svg" alt="LINE Official ของ [ชื่อลูกค้า]"></a> |
|
</div> |
|
|
|
<!-- ต้องสร้างไฟล์ /svg/yt.svg และ /svg/yt-w.svg (ฉบับสีขาวสำหรับเมนูมือถือ) เพิ่ม --> |
|
ผลที่คาดหวัง AI ผูกโดเมนกับช่อง YouTube ของแบรนด์ได้ · entity ชัดเจนขึ้นเมื่อ Instagram เหลือบัญชีเดียวที่ชัดเจน |
Score Impact +0.5 pts |
เวลาประมาณ 45 นาที |
|
#022 |
P3 |
ใส่ loading='lazy' และแปลงรูปเป็น WebP |
|
Dimension |
Technical |
|
หน้าที่แก้ |
ทุกหน้าที่มีรูป — เน้น /about.php, /gallery.php, /blog/ |
|
ส่วนที่แก้ |
<img> ทุกตัวที่ไม่ได้อยู่ครึ่งบนของหน้าจอ |
|
ปัญหา |
รูปเกือบทั้งหมดบนเว็บเป็น .jpg และ .png พบ .webp เพียงไฟล์เดียวคือ [ไฟล์รูปลูกค้า] และไม่พบ loading='lazy' บนรูปเลยสักตัว มีเฉพาะบน iframe แผนที่ หน้า /about.php มีรูป 10 รูปที่โหลดพร้อมกันหมดตั้งแต่เปิดหน้า ซึ่งรวมกันหลายร้อยกิโลไบต์ทั้งที่ผู้ใช้ยังไม่ได้เลื่อนลงไปเห็น |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- lazy load — ทุกรูปที่อยู่ต่ำกว่าครึ่งบนหน้าจอ --> |
|
<img src="ab-03.jpg" alt="..." width="720" height="480" loading="lazy" decoding="async"> |
|
|
|
<!-- WebP พร้อม fallback --> |
|
<picture> |
|
<source srcset="ab-01.webp" type="image/webp"> |
|
<img src="ab-01.jpg" alt="..." width="720" height="720" loading="lazy" decoding="async"> |
|
</picture> |
|
|
|
# แปลงรูปทั้งโฟลเดอร์เป็น WebP |
|
for f in *.jpg; do cwebp -q 82 "$f" -o "${f%.jpg}.webp"; done |
|
|
|
# ตรวจว่าเหลือรูปที่ยังไม่ lazy กี่ตัว |
|
curl -s https://[โดเมนลูกค้า]/about.php | grep -o '<img[^>]*>' | grep -vc 'loading=' |
|
ผลที่คาดหวัง หน้า /about.php โหลดเร็วขึ้นชัดเจน · ขนาดรูปรวมลดลงประมาณ 25–35% จากการใช้ WebP |
Score Impact +0.4 pts |
เวลาประมาณ 2–3 ชั่วโมง |
|
#023 |
P3 |
ลดโครงสร้าง nav ที่ซ้ำ 3 ชุด และเปลี่ยนลิงก์ javascript: เป็นปุ่มจริง |
|
Dimension |
Crawlability / Technical |
|
หน้าที่แก้ |
ทุกหน้าทั้ง 15 หน้า |
|
ส่วนที่แก้ |
.ftmenu, .topmenu และ .so-nav · <a href='javascript:menuOpen();'> |
|
ปัญหา |
ทุกหน้ามี nav ซ้ำ 3 ชุดใน DOM คือ .ftmenu ที่ footer, .topmenu ที่ลอยด้านบน และ .so-nav สำหรับเมนูมือถือ ทำให้ลิงก์เดียวกันถูกนับซ้ำ 3 รอบต่อหน้า และ HTML บวมโดยไม่จำเป็น นอกจากนี้ยังมีลิงก์ที่ตั้ง href='javascript:menuOpen();' และ href='javascript:menuClose();' รวม 30 จุดทั่วเว็บ ซึ่งเป็น anchor ที่ไม่ได้พาไปไหนจริง ควรเป็น <button> ตามความหมายที่ถูกต้อง |
วิธีแก้
Code / คำสั่งที่ใช้
|
<!-- ผิด (ปัจจุบัน) --> |
|
<a href="javascript:menuOpen();"><img src="/svg/nav.svg" alt="" class="smnav"></a> |
|
<a href="javascript:menuClose();"><img src="/svg/nav.svg" alt="" width="40"></a> |
|
|
|
<!-- ถูก --> |
|
<button type="button" class="smnav-btn" aria-label="เปิดเมนู" |
|
aria-expanded="false" aria-controls="mobile-menu"> |
|
<img src="/svg/nav.svg" alt="" class="smnav"> |
|
</button> |
|
|
|
<div class="floatmenu-sm-open hidden-pc inactive" id="mobile-menu"> |
|
<button type="button" class="so-close-btn" aria-label="ปิดเมนู"> |
|
<img src="/svg/nav.svg" alt="" width="40"> |
|
</button> |
|
... |
|
</div> |
|
|
|
<script> |
|
document.querySelector('.smnav-btn').addEventListener('click', function () { |
|
var m = document.getElementById('mobile-menu'); |
|
var open = m.classList.toggle('inactive') === false; |
|
this.setAttribute('aria-expanded', open); |
|
}); |
|
document.querySelector('.so-close-btn').addEventListener('click', function () { |
|
document.getElementById('mobile-menu').classList.add('inactive'); |
|
document.querySelector('.smnav-btn').setAttribute('aria-expanded', 'false'); |
|
}); |
|
</script> |
|
ผลที่คาดหวัง HTML เล็กลง · โครงสร้างลิงก์ชัดเจนขึ้นสำหรับ crawler · เข้าถึงได้ด้วยคีย์บอร์ดและ screen reader |
Score Impact +0.3 pts |
เวลาประมาณ 2 ชั่วโมง |
|
#024 |
P3 |
เขียนบทความใหม่ — ไม่มีบทความใหม่มา 21 เดือน |
|
Dimension |
Content / AI Overview |
|
หน้าที่แก้ |
https://[โดเมนลูกค้า]/blog/ |
|
ส่วนที่แก้ |
เนื้อหาใหม่ในระบบบทความ |
|
ปัญหา |
บทความทั้ง 7 บทลงวันที่ 21 ถึง 28 พฤศจิกายน 2024 คือไม่มีบทความใหม่มา 21 เดือน และแต่ละบทมีความยาวเพียง 18 ถึง 156 คำ โดยบทที่สั้นที่สุดคือ การแสดง มีแค่ 18 คำ ทุกบทยังเขียนคำโปรยซ้ำกับย่อหน้าแรกของเนื้อหาแบบคำต่อคำ ซึ่งเป็นสาเหตุหนึ่งที่โดนหักค่าปรับ thin content 15 คะแนน แบรนด์นี้มีวัตถุดิบเนื้อหาที่ดีมากอยู่แล้ว ทั้งเรื่องช่างฝีมือ สถาปัตยกรรม และชุมชน แต่ยังไม่ได้ถูกเขียนออกมาเป็นหน้าที่ AI หยิบไปตอบได้ |
วิธีแก้
Code / คำสั่งที่ใช้
|
# หัวข้อที่แนะนำ — มาจากคำค้นจริงที่พบระหว่าง audit |
|
|
|
1. "ร้านอาหาร[จังหวัด]พาสัตว์เลี้ยงได้ไหม" |
|
-> ใช้กับ slug /blog/3/pet-friendly/ ที่มีอยู่แล้ว (ดู ticket #017) |
|
|
|
2. "ล่องเรือแม่น้ำ[จังหวัด] 3 สาย — เส้นทาง เวลา ราคา และจองอย่างไร" |
|
-> ขยายจากบทความ /blog/1/ล่องเรือ/ ที่มีแค่ 46 คำ |
|
|
|
3. "ตำรับอาหารชาว[อำเภอ/ตำบล] ต่างจากอาหารชาววัง[จังหวัด]อย่างไร" |
|
-> ตอบคำถามที่ทำให้แบรนด์นี้ต่างจากร้านอื่นใน[จังหวัด] |
|
|
|
4. "อาคารบล็อกแก้ว 20,000 ก้อน — เบื้องหลังงานที่ได้รางวัล [นิตยสารต่างประเทศ]" |
|
-> ผูกกับ entity ที่มี authority สูงสุดของแบรนด์ |
|
|
|
5. "เที่ยว[จังหวัด] 1 วัน — เส้นทางจากวัดไชยวัฒนารามถึงมื้อเย็นริมน้ำ" |
|
-> จับ traffic นักท่องเที่ยวที่ยังไม่รู้จักแบรนด์ |
|
|
|
# เกณฑ์ขั้นต่ำต่อบท |
|
- ความยาว 600 คำขึ้นไป |
|
- H2 อย่างน้อย 3 หัวข้อ เขียนเป็นรูปคำถามที่คนค้นจริง |
|
- มีตัวเลขหรือข้อเท็จจริงที่ดึงไปตอบได้ทันที (เวลา ราคา ระยะทาง จำนวน) |
|
- มี BlogPosting schema พร้อม author, datePublished, dateModified |
|
- คำโปรยต้องไม่ซ้ำกับย่อหน้าแรกแบบคำต่อคำ |
|
ผลที่คาดหวัง ปลดค่าปรับ thin content −15 อย่างถาวร · เพิ่มหน้าที่มีสิทธิ์ถูก cite ใน AI Overview อีก 5 หน้า |
Score Impact +2.1 pts |
เวลาประมาณ 5 บท ประมาณ 3–5 วันทำงาน |
6 Page-by-Page Tickets สรุปว่าแต่ละหน้าต้องแก้อะไรบ้าง
ทุกหน้าทั้ง 15 หน้า
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#006 |
เขียน title และ meta description ใหม่ให้ไม่ซ้ำกันทั้ง 15 หน้า |
<title> และ <meta name='description'> ใน <head> |
P1 |
1–1.5 ชั่วโมง |
|
#007 |
ใส่ canonical tag ทุกหน้า |
<link rel='canonical'> ใน <head> |
P1 |
45 นาที |
|
#008 |
ใส่ OG tag และ twitter:card ทุกหน้า |
<meta property='og:*'> และ <meta name='twitter:*'> ใน <head> |
P1 |
1 ชั่วโมง (รวมทำรูป og:image) |
|
#011 |
ถอด translate='no' และ class='notranslate' ออกจาก <html> |
<html lang='th' class='notranslate' translate='no'> |
P1 |
20 นาที |
|
#014 |
เพิ่ม BreadcrumbList และ WebSite schema |
<script type='application/ld+json'> ใน <head> |
P2 |
1 ชั่วโมง |
|
#023 |
ลดโครงสร้าง nav ที่ซ้ำ 3 ชุด และเปลี่ยนลิงก์ javascript: เป็นปุ่มจริง |
.ftmenu, .topmenu และ .so-nav · <a href='javascript:menuOpen();'> |
P3 |
2 ชั่วโมง |
https://[โดเมนลูกค้า]/ (หน้าแรก)
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#009 |
ใส่ H1 ให้หน้าแรก และแก้ H1 ซ้อน 2 ตัวบนหน้าวิดีโอ |
หน้าแรก: <div class='hi_p1'> และ <div class='hi_p2'> · หน้าวิดีโอ: <h1 class='size32 size24-sm size18-xs'> |
P1 |
45 นาที |
|
#018 |
แก้ preload ของวิดีโอ 42.8 MB ลบรูป fallback ที่โหลดฟรี และลบ JS ที่ใส่ source ซ้ำ |
<video> ใน .container · <div class='hero_sim'><img src='hero_ab.jpg'> · script ท้ายหน้า |
P2 |
1–2 ชั่วโมง |
/blog/3/pet-friendly/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#016 |
ใส่ BlogPosting schema, author และ dateModified ให้บทความทั้ง 7 บท |
<head> ของ template บทความ + บล็อกเนื้อหา .blogs-fluid |
P2 |
2 ชั่วโมง |
|
#017 |
แก้ slug บทความ 2 บทที่ไม่ตรงกับเนื้อหา พร้อมตั้ง 301 |
URL slug และ rewrite rule ของ /blog/ |
P2 |
1 ชั่วโมง (ทางเลือก A) · 3–4 ชั่วโมง (ทางเลือก B รวมเขียนบทความ) |
/blog/6/ingredients/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#016 |
ใส่ BlogPosting schema, author และ dateModified ให้บทความทั้ง 7 บท |
<head> ของ template บทความ + บล็อกเนื้อหา .blogs-fluid |
P2 |
2 ชั่วโมง |
|
#017 |
แก้ slug บทความ 2 บทที่ไม่ตรงกับเนื้อหา พร้อมตั้ง 301 |
URL slug และ rewrite rule ของ /blog/ |
P2 |
1 ชั่วโมง (ทางเลือก A) · 3–4 ชั่วโมง (ทางเลือก B รวมเขียนบทความ) |
ทั้งโดเมน — ระดับ CDN / hPanel ไม่ใช่ระดับไฟล์
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#001 |
ปลดบล็อก GPTBot และ meta-externalagent ที่ Hostinger CDN |
Hostinger hPanel > Security หรือ Website > สวิตช์บล็อก AI crawler (edge rule ที่ server: hcdn) |
P0 |
15–30 นาที (ถ้าต้องเปิด ticket กับ Hostinger รอเพิ่ม 1–2 วัน) |
https://[โดเมนลูกค้า]/menu.php
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#002 |
ใส่เมนูจริงพร้อมราคาลงหน้า /menu.php แล้วผูก Restaurant + Menu schema |
<div class='container aa-meal'> — ตอนนี้ทั้ง div มีแค่ปุ่ม LINE หนึ่งปุ่ม |
P0 |
3–4 ชั่วโมง (หลังได้ไฟล์เมนูจากลูกค้า) |
ทุกหน้าทั้ง 15 หน้า — ปุ่ม TH/EN อยู่ใน nav ทั้ง 3 ชุด
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#003 |
แก้ลิงก์ /en/ ที่เป็นทางตัน 45 จุด และตัดสินใจเรื่องเว็บภาษาอังกฤษ |
<a href='/en/...' class='mod-lang'> ใน .ftmenu, .topmenu และ .so-nav · และ <html lang> · rewrite rule ของ /en/ |
P0 |
ทางเลือก A 2–3 วัน (รวมงานแปล) · ทางเลือก B 30 นาที |
/en/ และทุก URL ใต้ /en/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#003 |
แก้ลิงก์ /en/ ที่เป็นทางตัน 45 จุด และตัดสินใจเรื่องเว็บภาษาอังกฤษ |
<a href='/en/...' class='mod-lang'> ใน .ftmenu, .topmenu และ .so-nav · และ <html lang> · rewrite rule ของ /en/ |
P0 |
ทางเลือก A 2–3 วัน (รวมงานแปล) · ทางเลือก B 30 นาที |
https://[โดเมนลูกค้า]/robots.txt
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#004 |
สร้าง robots.txt และ sitemap.xml (ตอนนี้ 404 ทั้งคู่) |
ไฟล์ static ที่ document root |
P0 |
1–2 ชั่วโมง |
https://[โดเมนลูกค้า]/sitemap.xml
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#004 |
สร้าง robots.txt และ sitemap.xml (ตอนนี้ 404 ทั้งคู่) |
ไฟล์ static ที่ document root |
P0 |
1–2 ชั่วโมง |
ทุกหน้าทั้ง 15 หน้า — วาง JSON-LD ใน <head> ของ template กลาง
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#005 |
ใส่ Restaurant + Organization schema พร้อม sameAs และ NAP ที่ถูกต้อง ทุกหน้า |
<script type='application/ld+json'> ใน <head> |
P1 |
2 ชั่วโมง |
https://[โดเมนลูกค้า][หน้าวิดีโอ]
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#009 |
ใส่ H1 ให้หน้าแรก และแก้ H1 ซ้อน 2 ตัวบนหน้าวิดีโอ |
หน้าแรก: <div class='hi_p1'> และ <div class='hi_p2'> · หน้าวิดีโอ: <h1 class='size32 size24-sm size18-xs'> |
P1 |
45 นาที |
https://[โดเมนลูกค้า]/contact.php
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#010 |
ประกาศที่อยู่และอีเมลบนหน้าติดต่อและ footer |
<div class='contact-info'> บนหน้าติดต่อ และ <div class='footer'> ในทุกหน้า |
P1 |
45 นาที (หลังได้ข้อมูลยืนยันจากลูกค้า) |
footer ของทุกหน้า
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#010 |
ประกาศที่อยู่และอีเมลบนหน้าติดต่อและ footer |
<div class='contact-info'> บนหน้าติดต่อ และ <div class='footer'> ในทุกหน้า |
P1 |
45 นาที (หลังได้ข้อมูลยืนยันจากลูกค้า) |
ทุกหน้าทั้ง 15 หน้า — ดูตาราง alt เต็มในหัวข้อ 7
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#012 |
เพิ่ม alt text ให้รูปที่ขาดหรือกว้างเกินไป 79 จุด (28 ไฟล์ที่ไม่ซ้ำกัน) |
attribute alt ของ <img> ทุกตัว |
P2 |
2–3 ชั่วโมง |
https://[โดเมนลูกค้า]/gallery.php
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#013 |
แก้หน้าแกลเลอรี่ให้ใช้ <img> จริงแทน CSS background |
<div class='gl-item'>Image39.jpg</div> ทั้ง 21 กล่อง และ script jQuery ท้ายหน้า |
P2 |
2 ชั่วโมง |
https://[โดเมนลูกค้า]/contact.php หรือหน้าใหม่ /faq.php
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#015 |
เพิ่ม FAQ จริงบนหน้าเว็บพร้อม FAQPage schema |
เนื้อหาใหม่ + <script type='application/ld+json'> |
P2 |
2–3 ชั่วโมง |
/blog/1/ล่องเรือ/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#016 |
ใส่ BlogPosting schema, author และ dateModified ให้บทความทั้ง 7 บท |
<head> ของ template บทความ + บล็อกเนื้อหา .blogs-fluid |
P2 |
2 ชั่วโมง |
/blog/2/ภาชนะ/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#016 |
ใส่ BlogPosting schema, author และ dateModified ให้บทความทั้ง 7 บท |
<head> ของ template บทความ + บล็อกเนื้อหา .blogs-fluid |
P2 |
2 ชั่วโมง |
/blog/4/สถาปัตยกรรม/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#016 |
ใส่ BlogPosting schema, author และ dateModified ให้บทความทั้ง 7 บท |
<head> ของ template บทความ + บล็อกเนื้อหา .blogs-fluid |
P2 |
2 ชั่วโมง |
/blog/5/ป้ายาย/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#016 |
ใส่ BlogPosting schema, author และ dateModified ให้บทความทั้ง 7 บท |
<head> ของ template บทความ + บล็อกเนื้อหา .blogs-fluid |
P2 |
2 ชั่วโมง |
/blog/7/การแสดง/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#016 |
ใส่ BlogPosting schema, author และ dateModified ให้บทความทั้ง 7 บท |
<head> ของ template บทความ + บล็อกเนื้อหา .blogs-fluid |
P2 |
2 ชั่วโมง |
ทุกหน้าทั้ง 15 หน้า — ระดับ header และการเรียก CSS
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#019 |
แก้นโยบายแคชและ cache-bust ที่เปลี่ยนทุกนาที |
<link rel='stylesheet' href='/styles.css?nc=YYYYMMDDHHmm'> และ header Cache-Control จาก PHP session |
P2 |
1 ชั่วโมง |
https://web.[โดเมนลูกค้า]/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#020 |
ใส่ noindex ให้หน้า placeholder ของ subdomain web.[โดเมนลูกค้า] |
robots.txt หรือ header X-Robots-Tag ที่ subdomain |
P2 |
30 นาที |
footer และ nav ทั้ง 3 ชุดในทุกหน้า
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#021 |
เพิ่มลิงก์ YouTube ใน footer และตัดสินใจเรื่อง Instagram สองบัญชี |
<div class='sns'> ในทุกหน้า |
P3 |
45 นาที |
ทุกหน้าที่มีรูป — เน้น /about.php, /gallery.php, /blog/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#022 |
ใส่ loading='lazy' และแปลงรูปเป็น WebP |
<img> ทุกตัวที่ไม่ได้อยู่ครึ่งบนของหน้าจอ |
P3 |
2–3 ชั่วโมง |
https://[โดเมนลูกค้า]/blog/
|
Ticket |
หัวข้อ |
สิ่งที่ต้องเปลี่ยน |
Pri |
เวลา |
|
#024 |
เขียนบทความใหม่ — ไม่มีบทความใหม่มา 21 เดือน |
เนื้อหาใหม่ในระบบบทความ |
P3 |
5 บท ประมาณ 3–5 วันทำงาน |
7 ตาราง Alt Text ครบทุกรูป ข้อความจริงที่ต้องใส่ — ใช้กับ ticket #012 และ #013
|
ทุกรูปในตารางนี้เปิดดูภาพจริงแล้วก่อนเขียน ไม่ได้เดาจากชื่อไฟล์ รูปทั้งหมด 203 tag · ต้องแก้ 79 จุด · ไฟล์ที่ไม่ซ้ำกัน 28 ไฟล์ · coverage ปัจจุบัน 61% · เพิ่มเติมมีรูปแกลเลอรี่อีก 21 รูปที่เป็น CSS background จึงใส่ alt ไม่ได้จนกว่าจะทำ ticket #013 ก่อน ลำดับการทำ: รูปรางวัลก่อน (มูลค่าสูงสุดเพราะชื่อรางวัลเป็น entity ที่มี authority อยู่แล้ว) จากนั้นรูปที่ตอบคำถามลูกค้าได้ตรงๆ เช่น ล่องเรือ การแสดง สำรับ แล้วค่อยทำที่เหลือ |
โลโก้และไอคอน (ทุกหน้า)
|
ไฟล์ (ค่าปัจจุบัน) |
ข้อความฝั่งไทย |
ข้อความฝั่ง /en/ |
|
/svg/aa-color.svg (ปัจจุบัน alt="" · ปรากฏ 45 ครั้ง) |
โลโก้ [ชื่อลูกค้า] [ชื่อลูกค้า] [จังหวัด] |
[ชื่อลูกค้า] logo |
|
/svg/nav.svg (ปัจจุบัน alt="" · ปรากฏ 30 ครั้ง) |
ไม่ต้องแก้ — เป็นไอคอนตกแต่งของปุ่มเมนู alt="" ถูกแล้ว (แต่ควรเปลี่ยน <a> เป็น <button aria-label> ตาม ticket #023) |
— |
|
/svg/ig.svg · fb.svg · line.svg (ปัจจุบัน alt="instagram" ฯลฯ) |
Instagram ของ [ชื่อลูกค้า] · Facebook ของ [ชื่อลูกค้า] · LINE Official ของ [ชื่อลูกค้า] |
Instagram · Facebook · LINE Official of [ชื่อลูกค้า] |
หน้าแรก (index.php)
|
ไฟล์ (ค่าปัจจุบัน) |
ข้อความฝั่งไทย |
ข้อความฝั่ง /en/ |
|
hero_ab.jpg (ปัจจุบัน alt="") |
แม่ครัวชุมชน[อำเภอ/ตำบล]ยืนหน้าตึกป้าอี้ อาคารบล็อกแก้[ชื่อลูกค้ารายอื่น] [หมายเหตุ] ticket #018 แนะนำให้ย้ายรูปนี้ออกจากใน <video> เพราะโหลดฟรีโดยไม่เคยแสดงผล ถ้าลบก็ไม่ต้องเขียน alt |
[ตำบล] community cook at the [ชื่อบุคคล] glass-block building by the [แม่น้ำ] |
|
hi_pic_rv4.jpg (ปัจจุบัน alt="") |
สำรับอาหารไทยพื้นบ้าน[จังหวัด] เสิร์ฟในภาชนะดินเผาและเบญจรงค์ทำมือ |
[จังหวัด] heritage Thai set menu served in handmade earthenware and benjarong |
เกี่ยวกับเรา (about.php)
|
ไฟล์ (ค่าปัจจุบัน) |
ข้อความฝั่งไทย |
ข้อความฝั่ง /en/ |
|
hero_rv3.jpg · hero_rv3_sm.jpg (ปัจจุบัน alt="") |
ร้านอาหา[ชื่อลูกค้ารายอื่น] [จังหวัด] มุมสูงยามพลบค่ำ อาคารบล็อกแก้ว 5 หลังในชุมชน[อำเภอ/ตำบล] |
Aerial dusk view of the riverside restaurant in [จังหวัด], five glass-block buildings in [ตำบล] |
|
ab-01.jpg (ปัจจุบัน alt="") |
บาร์ชนบทในอาคารบล็อกแก้ว เคาน์เตอร์ทองเหลืองและผนังบล็อกแก้วสองชั้น |
Countryside bar with brass counter inside the double-height glass-block hall |
|
ab-02.jpg (ปัจจุบัน alt="") |
รินน้ำสมุนไพรลงบนข้าวสวยหุงหม้อดิน เสิร์ฟในกระติบไม้ไผ่บนใบตอง |
Pouring herbal infusion over clay-pot rice served in a bamboo basket on banana leaf |
|
ab-03.jpg (ปัจจุบัน alt="") |
[ชื่อบุคคล] ช่างปั้นดินเผาคนสุดท้ายแห่ง[ตำบล] ตีขึ้นรูปหม้อดินด้วยไม้ลาย |
[ชื่อบุคคล], the last potter of [ตำบล], shaping a clay pot with a wooden paddle |
|
ab-04.jpg (ปัจจุบัน alt="") |
อาคารบล็อกแก้วทรงสามเหลี่ยมยามเย็น ผลงานรางวัล [รางวัลร้านอาหารระดับสากล] จาก [นิตยสารต่างประเทศ] |
Triangular glass-block buildings at dusk, winner of [นิตยสารต่างประเทศ] [รางวัลร้านอาหารระดับสากล] |
|
ab-05.jpg (ปัจจุบัน alt="") |
กิจกรรมห่อข้าวต้มมัดด้วยใบตอง ผู้มาเยือนเรียนกับแม่ป้าในชุมชน |
Wrapping khao tom mat in banana leaves with community elders |
|
ab-06.jpg (ปัจจุบัน alt="") |
ล่องเรือชมโบราณสถานอยุธย[ชื่อลูกค้ารายอื่น] เรือของ [ชื่อลูกค้า] |
River cruise past [จังหวัด]'s ancient temple ruins on [ชื่อลูกค้า] boat |
|
ab-07.jpg (ปัจจุบัน alt="") |
สำรับรองท้องยามค่ำ ของว่างไทยพื้นบ้านในกระติบไม้ไผ่บนใบตอง |
Evening Thai snack set served in a bamboo basket on banana leaf |
|
thai-dance.jpg (ปัจจุบัน alt="") |
การแสดงนาฏศิลป์ไทยของเด็กนักเรียนทุกเย็นวันเสาร์อาทิตย์ ริมแม่น้ำ[จังหวัด] |
Thai classical dance by local schoolchildren every weekend evening by the river |
รางวัล (awards.php) — alt ที่มีมูลค่าสูงสุดของทั้งเว็บ ทำก่อนเสมอ
|
ไฟล์ (ค่าปัจจุบัน) |
ข้อความฝั่งไทย |
ข้อความฝั่ง /en/ |
|
imgs/award-rv2.jpg (ปัจจุบัน alt="[รางวัลร้านอาหารระดับสากล]") |
หน้ารางวัล [รางวัลร้านอาหารระดับสากล] ในนิตยสาร [นิตยสารต่างประเทศ] ระบุ [ชื่อลูกค้า] โดย [สตูดิโอออกแบบ] |
[นิตยสารต่างประเทศ] [รางวัลร้านอาหารระดับสากล] award page featuring [ชื่อลูกค้า] by [สตูดิโอออกแบบ] |
|
imgs/award-3-800.jpg (ปัจจุบัน alt="[รางวัลออกแบบระดับสากล]") |
หน้าประกาศ [รางวัลออกแบบระดับสากล] สาขา Social Impact จาก [สื่อออกแบบต่างประเทศ] |
[สื่อออกแบบต่างประเทศ] [รางวัลออกแบบระดับสากล] Social Impact announcement page |
|
imgs/[ไฟล์รูปลูกค้า] (ปัจจุบัน alt="[นิตยสารต่างประเทศ] 2022") |
ปกนิตยสาร [นิตยสารต่างประเทศ] ฉบับกุมภาพันธ์ 2022 ประกาศผล Design Awards 2022 |
[นิตยสารต่างประเทศ] magazine February 2022 cover announcing the Design Awards 2022 |
|
imgs/[ไฟล์รูปลูกค้า] (ปัจจุบัน alt="[รางวัลอาหารไทยระดับประเทศ]") |
ใบประกาศ [รางวัลอาหารไทยระดับประเทศ] มอบให้ [ชื่อลูกค้า] [จังหวัด] โดยกรมพัฒนาธุรกิจการค้า กันยายน 2024 |
[รางวัลอาหารไทยระดับประเทศ] certificate awarded to [ชื่อลูกค้า] by Thailand's Department of Business Development, September 2024 |
แกลเลอรี่ (gallery.php) — ทำพร้อม ticket #013
|
ไฟล์ (ค่าปัจจุบัน) |
ข้อความฝั่งไทย |
ข้อความฝั่ง /en/ |
|
gallery_cover_4-3_light.jpg (ปัจจุบัน alt="") |
โต๊ะอาหารริมผนังบล็อกแก้ว จัดสำรับไทยพร้อมเสิร์ฟ วิวสวนผ่านหน้าต่างไม้ |
Dining table by the glass-block wall set with a full Thai meal and garden view |
|
gallery/Image18-2.jpg ถึง Image42.jpg (21 รูป — ปัจจุบันไม่มี <img> เลย) |
ต้องแปลงเป็น <img> ก่อนตาม ticket #013 แล้วจึงเขียน alt ทีละรูป สูตร: [สิ่งที่คนค้นจริง] + [บริบทสถานที่] เช่น "สำรับอาหารไทยพื้นบ้านเสิร์ฟในถ้วยดินเผาทำมือ [ชื่อลูกค้ารายอื่น] [จังหวัด]" ใส่ชื่อแบรนด์ไม่เกิน 12 รูปจาก 21 รูป (60%) |
แปลเป็นอังกฤษเมื่อทำหน้า /en/gallery.php ตาม ticket #003 |
วิดีโอ (video.php) — ปัจจุบัน alt="Youtube" เหมือนกันทั้ง 6 ตัว
|
ไฟล์ (ค่าปัจจุบัน) |
ข้อความฝั่งไทย |
ข้อความฝั่ง /en/ |
|
[โฮสต์รูปภายนอก] |
Time-Lapse การก่อสร้างอาคารบล็อกแก้วของ [ชื่อลูกค้า] |
Time-lapse of the glass-block building construction at [ชื่อลูกค้า] |
|
[โฮสต์รูปภายนอก] |
ผศ. [สถาปนิก] ผู้ก่อตั้ง [ชื่อลูกค้า] เล่าแนวคิดงานสถาปัตยกรรม |
[สถาปนิก], founder of [ชื่อลูกค้า], on the design concept |
|
[โฮสต์รูปภายนอก] |
คุณค่าของร้านคือการทำให้ผู้คนในชุมชนกลับมาเห็นคุณค่าของตัวเอง |
How the restaurant helps the community rediscover its own worth |
|
[โฮสต์รูปภายนอก] |
ความประทับใจจากผู้มาเยือน [ชื่อลูกค้า] |
Guest impressions of a visit to [ชื่อลูกค้า] |
|
[โฮสต์รูปภายนอก] |
อิ่มตา อิ่มใจ อิ่มท้อง ประสบการณ์มื้ออาหารไทยพื้นบ้านริมแม่น้ำ[จังหวัด] |
A riverside [จังหวัด] meal that fills the eyes, the heart and the stomach |
|
[โฮสต์รูปภายนอก] |
สำรับรองท้องสำหรับสองท่าน ของว่างไทยพื้นบ้านยามบ่าย |
Afternoon Thai snack set for two |
บทความ (blog) — ปัจจุบัน alt เป็นคำเดียวกว้างๆ
|
ไฟล์ (ค่าปัจจุบัน) |
ข้อความฝั่งไทย |
ข้อความฝั่ง /en/ |
|
ul/h200ztu5dd/…ล่องเรือ (ปัจจุบัน alt="ล่องเรือ") |
เรือล่องแม่น้ำของร้านแล่นผ่านโบราณสถานวัดไชยวัฒนาราม [จังหวัด] |
The restaurant's river boat passing [โบราณสถาน] ruins in [จังหวัด] |
|
[พาธรูป]…ภาชนะ (ปัจจุบัน alt="ภาชนะ") |
โต๊ะยาวจัดสำรับไท[ชื่อลูกค้ารายอื่น] ใช้ภาชนะดินเผาและเบญจรงค์ทำมือทุกใบ |
Long riverside table set with a Thai meal served entirely in handmade earthenware and benjarong |
|
ul/h219ggjqua/…รางวัล (ปัจจุบัน alt="รางวัล") |
หน้ารางวัล [รางวัลร้านอาหารระดับสากล] ในนิตยสาร [นิตยสารต่างประเทศ] ของ [ชื่อลูกค้า] |
[นิตยสารต่างประเทศ] [รางวัลร้านอาหารระดับสากล] feature page for [ชื่อลูกค้า] |
|
ul/h219hpp6l8/…สถาปัตยกรรม (ปัจจุบัน alt="สถาปัตยกรรม") |
อาคารบล็อกแก้ว 20,000 ก้อนทรงสามเหลี่ยมยามเย็น พร้อมลานไม้และต้นไม้กลางคอร์ต |
Triangular buildings of 20,000 glass blocks at dusk with wooden deck and courtyard trees |
|
ul/h219jfj966/…ป้ายาย (ปัจจุบัน alt="ป้ายาย") |
แม่ครัวสูงวัยชุมชน[อำเภอ/ตำบล]ยกหม้อดินจากเตาฟืน ผู้สืบทอดสูตรอาหารตำรับชาวบ้าน |
Elderly [ตำบล] cook lifting a clay pot from the wood fire, keeper of the village recipes |
|
ul/h219kuhyoh/…อาหาร (ปัจจุบัน alt="อาหาร") |
สำรับรองท้องสามชั้น ของว่างไทยพื้นบ้านในถ้วยดินเผาและเบญจรงค์ พร้อมชาร้อน |
Three-tier afternoon Thai snack set in earthenware and benjarong cups with hot tea |
|
ul/h27uso01r9/…การแสดง (ปัจจุบัน alt="การแสดง") |
เด็กนักเรียนแต่งชุดไทยแสดงนาฏศิลป์หน้าอาคารบล็อกแก้วยามเย็น |
Schoolgirl in Thai costume performing classical dance in front of the lit glass-block building |
|
mce/ss/h27uxwmy0p_…png (ในเนื้อบทความที่ 7 · ปัจจุบัน alt="") |
การแสดงศิลปวัฒนธรรมไทยของเด็กนักเรียนที่ลานไม้ริมแม่น้ำ |
— |
หลักการเขียน alt — ใช้เขียนเองได้เมื่อเพิ่มรูปใหม่ในอนาคต
1. ขึ้นต้นด้วยสิ่งที่คนพิมพ์ค้นจริง — ชื่อเมนู ประเภทบรรยากาศ ชื่อบริการ ไม่ใช่สิ่งของที่เห็นในรูป
2. ใส่ชื่อแบรนด์เฉพาะรูปหลัก ประมาณครึ่งหนึ่งของรูปในหน้าเดียวกัน ไม่ใช่ทุกรูป (เกิน 60% Google นับเป็นการยัดคีย์เวิร์ด)
3. ใส่คำระบุที่ตั้งเฉพาะรูปสถานที่และบรรยากาศ เช่น [จังหวัด] [ชื่อลูกค้ารายอื่น] [อำเภอ/ตำบล]
4. ใช้คำเดียวกับที่ลูกค้าถาม เช่น พาสัตว์เลี้ยงได้ ล่องเรือ มีการแสดง ที่จอดรถ
5. ยาว 10–16 คำ อ่านเป็นประโยคปกติ ห้ามเขียนเป็นคำโดดคั่นจุลภาค
6. ห้ามใส่ราคาใน alt เพราะราคาเปลี่ยนแล้ว alt จะขัดกับข้อความบนหน้า
7. ไอคอนตกแต่งใส่ alt="" ส่วนปุ่มให้บอกหน้าที่ของปุ่ม ไม่ใส่คำค้น
ตารางเปลี่ยนชื่อไฟล์รูป
|
ชื่อปัจจุบัน |
ชื่อใหม่ที่แนะนำ |
หมายเหตุ |
|
hi_pic_rv4.jpg |
homepage-thai-set-menu-earthenware.jpg |
หน้าแรก · อ้างถึงที่เดียว |
|
hero_rv3.jpg |
[ไฟล์รูป].jpg |
about.php · อ้างถึงที่เดียว |
|
hero_rv3_sm.jpg |
[ไฟล์รูป].jpg |
about.php · อ้างถึงที่เดียว |
|
ab-01.jpg ถึง ab-07.jpg |
about-bar-glassblock.jpg · about-claypot-rice.jpg · about-pottery-khlong-sabua.jpg · about-glassblock-buildings-dusk.jpg · about-khaotommat-workshop.jpg · [ไฟล์รูป].jpg · about-evening-snack-set.jpg |
about.php · อ้างถึงที่เดียวทั้ง 7 ไฟล์ |
|
gallery_cover_4-3_light.jpg |
gallery-cover-thai-set-glassblock.jpg |
gallery.php · อ้างถึงที่เดียว |
|
imgs/award-rv2.jpg |
imgs/wallpaper-best-restaurant-2022-feature.jpg |
awards.php · อ้างถึงที่เดียว |
|
imgs/award-3-800.jpg |
imgs/[สื่อออกแบบต่างประเทศ]-design-prize-2021-social-impact.jpg |
awards.php · อ้างถึงที่เดียว |
|
ห้ามเปลี่ยนชื่อไฟล์ชุดนี้ ห้ามเปลี่ยนชื่อ /svg/aa-color.svg และ /svg/aa-white.svg เด็ดขาด — นอกจากจะถูกอ้างถึง 45 จุดใน HTML แล้ว ยังถูกเรียกจาก JavaScript ที่สลับโลโก้ตอน scroll ด้วย ($('.toplogo,.smlogo').attr('src','/svg/aa-color.svg')) ความเสี่ยงที่หน้าจะพังมากกว่าประโยชน์ที่ได้ · ส่วนรูปแกลเลอรี่ 21 ไฟล์ (Image18-2.jpg ถึง Image42.jpg) ให้เปลี่ยนชื่อพร้อมกับ ticket #013 ในคราวเดียว เพราะ ticket นั้นเขียน markup ใหม่ทั้งหน้าอยู่แล้ว จะได้ไม่ต้องแก้สองรอบ · hero_ab.jpg ไม่ต้องเปลี่ยนชื่อเพราะ ticket #018 แนะนำให้ลบทิ้ง |
8 Off-Site Presence งานที่ลูกค้าต้องทำเอง — ไม่ใช่งาน developer
|
อ่านก่อนเริ่ม รายการในหัวข้อนี้เป็นคนละงานกับ ticket ด้านบน ทำโดยลูกค้าหรือทีมการตลาด ไม่ใช่ developer และผลไม่ขึ้นทันที ต้องรอ Google index หลายวันถึงหลายสัปดาห์ ตอน re-audit อาจยังขึ้นสถานะ PARTIAL แม้ทำครบแล้ว กรณีของลูกค้ารายนี้พิเศษกว่าเว็บทั่วไปมาก — 6 จาก 8 ช่องได้เต็ม 10 อยู่แล้ว ทำให้ best 5 of 8 เต็ม 50 คะแนนตั้งแต่ยังไม่ทำอะไร สิ่งเดียวที่ฉุดคะแนนคือค่าปรับ NAP 10 คะแนน แปลว่างาน off-site ของแบรนด์นี้ไม่มีอะไรต้องสร้างใหม่เลย มีแต่ต้องแก้ข้อมูลให้ตรงกันและรักษาไม่ให้ตก · ห้ามเสียแรงไปสร้าง LinkedIn หรือ Pantip เพื่อหวังคะแนน เพราะช่องที่ 6 ถึง 8 ไม่ได้คะแนนเพิ่มแม้แต่คะแนนเดียว สถานะปัจจุบัน: GBP 10 · YouTube 10 · Social 10 · Directory 10 · Press 10 · UGC 10 · Forum 0 · LinkedIn 0 → best 5 of 8 = 50 → ×2 = 100 → NAP ไม่ตรง หัก 10 → 90/100 เป้าหมาย: ไม่ต้องสร้างช่องใหม่เลย — แค่แก้ NAP ให้ตรงกัน → best 5 of 8 = 50 → ×2 = 100 → ไม่หัก → 100/100 |
|
ID |
Pri |
งานที่ต้องทำ |
ตอนนี้ / ใครทำ |
รายละเอียด |
|
OS-1 |
P2 |
แก้ NAP ให้ตรงกันทุกช่อง และแจ้ง Wongnai แก้ชื่อ listing ที่ปนกับอีกแบรนด์ |
หัก 10 ลูกค้า + CiteLogics 2–3 ชม. + รอแพลตฟอร์มอนุมัติ |
นี่คือรายการ off-site ที่เร่งด่วนที่สุด และเป็นรายการเดียวที่ปลดค่าปรับได้ทันที 10 คะแนน ปัญหาที่พบคือ directory แต่ละเจ้าระบุที่อยู่กันคนละอำเภอ TripAdvisor ระบุ [ที่อยู่ลูกค้า], [อำเภอ] [รหัสไปรษณีย์] · Wongnai ระบุ 1 ตำบล [อำเภอ/ตำบล] อำเภอ[อำเภอ/ตำบล] โดยบ้านเลขที่ตัดหาย · [ไดเรกทอรีภายนอก] ระบุ [บ้านเลขที่], [จังหวัด] · [ลิงก์ภายนอก] ระบุอำเภอ [อำเภอ] · [ไดเรกทอรีภายนอก] ระบุ [ตำบล] Subdistrict ซึ่งเป็นคนละอำเภอกันทั้งหมด ต้นเหตุคือเว็บของแบรนด์เองไม่เคยประกาศที่อยู่ไว้ให้ยึด จึงต้องทำ ticket #010 ให้เสร็จก่อน แล้วค่อยไล่แก้ทุกช่องด้วยข้อความชุดเดียวกันทุกตัวอักษร ประเด็นที่สองซึ่งสำคัญไม่แพ้กันคือ listing บน Wongnai ID [listing ID] แสดงชื่อร้านเป็น [ชื่อลูกค้ารายอื่น] [จังหวัด][ชื่อลูกค้า] คือชื่อสองแบรนด์ต่อกันในบรรทัดเดียว ซึ่งเป็นสัญญาณสับสน entity โดยตรงสำหรับ AI ที่กำลังไล่ว่าร้านนี้คือใคร ต้องติดต่อ Wongnai ให้แยก listing และแก้ชื่อ พร้อมแก้เวลาเปิดเสาร์อาทิตย์จาก 10:00 เป็น 11:00 ให้ตรงกับเว็บ |
|
OS-2 |
P2 |
อัปคลิปใหม่ในช่อง YouTube ของแบรนด์ พร้อม transcript และ chapters |
10 / 10 ลูกค้า / ทีมคอนเทนต์ 1–2 สัปดาห์ |
ช่องนี้ได้เต็ม 10 อยู่แล้วจึงไม่ใช่การกู้คะแนน แต่เป็นการรักษาไม่ให้ตกลง คลิปใหม่สุดที่ฝังบนเว็บลงวันที่ 29 กุมภาพันธ์ 2024 คือเกือบ 2 ปีครึ่งแล้ว เกณฑ์ให้ 10 คะแนนคือมี activity ภายใน 90 วันหรือมีเนื้อหาตั้งแต่ 3 ชิ้นขึ้นไป ตอนนี้ผ่านด้วยเงื่อนไขที่สองเท่านั้น ให้อัปคลิปใหม่อย่างน้อย 3 คลิป ใส่ transcript ในคำอธิบายและแบ่ง chapters เพราะ transcript คือสิ่งที่ AI อ่านได้จริง ส่วนตัววิดีโอ AI อ่านไม่ได้ และให้ลิงก์กลับมาที่ [โดเมนลูกค้า] ในคำอธิบายทุกคลิป |
|
OS-3 |
P3 |
ตั้งกระทู้หรือร่วมสนทนาใน Pantip ห้องอาหารและห้องท่องเที่ยว |
0 / 10 ลูกค้า ต่อเนื่อง |
ค้น Pantip 2 รอบทั้งชื่อไทยและอังกฤษ รวมถึง Reddit และ Quora แล้วไม่พบกระทู้ที่พูดถึงแบรนด์นี้โดยตรงเลย ซึ่งน่าแปลกใจมากสำหรับร้านที่มีรีวิว Google กว่า 1,800 รายการ Pantip เป็นแหล่งที่ AI Overview ภาษาไทยดึงไปอ้างอิงบ่อยที่สุดแหล่งหนึ่ง วิธีที่ได้ผลคือรีวิวจากผู้ไปจริงพร้อมรูป ไม่ใช่การโพสต์โฆษณา ให้ชวนลูกค้าประจำที่ชอบเขียนรีวิวช่วยตั้งกระทู้ หรือตอบกระทู้ที่คนถามหาร้านอาหารใน[จังหวัด]อย่างจริงใจ ห้ามสแปมเพราะ Pantip ลบและแบนเร็วมาก |
|
OS-4 |
P3 |
สร้าง LinkedIn company page |
0 / 10 ลูกค้า 2–3 ชม. + โพสต์ต่อเนื่อง |
ค้นแล้วไม่พบ company page ของแบรนด์นี้ ซึ่งเป็น 1 ใน 2 ช่องที่ได้ 0 คะแนน แต่ต้องเตือนตามตรงว่าเนื่องจากคะแนนคิดจาก best 5 of 8 และตอนนี้มี 6 ช่องที่ได้เต็ม 10 อยู่แล้ว การเพิ่ม LinkedIn จะไม่เพิ่มคะแนน Off-Site เลยแม้แต่คะแนนเดียว จึงจัดเป็น P3 และแนะนำให้ทำก็ต่อเมื่อมีเหตุผลทางธุรกิจอื่นรองรับ เช่น ต้องการรับสมัครงาน หรือต้องการติดต่อลูกค้าองค์กรสำหรับงานเลี้ยงและสัมมนา ไม่ใช่ทำเพื่อคะแนน |
|
OS-5 |
P3 |
ผลักดัน Wikipedia หรือ Wikidata entry |
0 / 15 (นับที่ 5C ไม่ใช่ Off-Site) งาน PR / ลูกค้า 1–3 เดือน |
นี่คือช่องเดียวที่เหลืออยู่ในมิติ AI Citation Presence ซึ่งตอนนี้ได้ 85 จาก 100 โดยที่หายไป 15 คะแนนคือ Wikipedia หรือ Wikidata แบรนด์นี้มีคุณสมบัติที่เอื้อมถึงได้จริง ต่างจากลูกค้าทั่วไป เพราะมีรางวัลระดับสากล 3 รายการที่ตรวจสอบได้ มีสื่อออกแบบระดับนานาชาติเขียนถึงอย่าง [นิตยสารต่างประเทศ], [สื่อออกแบบต่างประเทศ] และ Archello และมีสถาปนิกผู้ก่อตั้งคือ ผศ. [สถาปนิก] แห่ง [สตูดิโอออกแบบ] ซึ่งเป็นบุคคลที่มีชื่อเสียงในวงการสถาปัตยกรรมโลก วิธีเริ่มคือสร้าง Wikidata item ก่อนซึ่งเกณฑ์ผ่อนปรนกว่า Wikipedia มาก โดยอ้างอิงแหล่งข่าวภายนอกที่มีอยู่แล้ว จากนั้นค่อยพิจารณาบทความ Wikipedia ข้อควรระวังคือห้ามให้แบรนด์เขียนเองเพราะขัดนโยบาย conflict of interest และจะถูกลบ |
|
OS-6 |
P3 |
รักษาช่องที่ได้เต็มอยู่แล้ว 6 ช่อง — อย่าปล่อยให้ตก |
10 / 10 × 6 ช่อง ลูกค้า ต่อเนื่อง |
ข้อความนี้สำคัญกว่าที่คิด เพราะ 6 ช่องที่ได้เต็ม 10 อยู่แล้วคือ Google Business Profile, YouTube, Social, Marketplace/Directory, Press และ UGC ซึ่งทำให้ได้ best-5-of-8 เต็ม 50 คะแนนก่อนหักค่า NAP หมายความว่าคะแนน Off-Site ของแบรนด์นี้ไม่มีอะไรต้องสร้างใหม่เลย มีแต่ต้องรักษา สิ่งที่ต้องทำคือตอบรีวิว Google ทุกรายการโดยเฉพาะรีวิวที่ให้ดาวน้อย โพสต์ Facebook และ Instagram อย่างสม่ำเสมอ และคอยตรวจว่า listing ตาม directory ยังถูกต้อง ห้ามเสียแรงไปสร้างช่องที่ 7 และ 8 เพราะไม่ได้คะแนนเพิ่มแม้แต่คะแนนเดียว |
9 Implementation Roadmap ลำดับการลงมือ 3 phase
|
Phase 1 — Week 1–2 คาดหวัง 61/100 |
Phase 2 — Month 1 คาดหวัง 78/100 |
Phase 3 — Month 2–3 คาดหวัง 88/100 (ceiling) |
|
• #001 ปลดบล็อก GPTBot ที่ Hostinger • #003 แก้ลิงก์ /en/ ที่เป็นทางตัน 45 จุด • #004 สร้าง robots.txt + sitemap.xml • #006 title + meta description 15 หน้า • #007 canonical tag ทุกหน้า • #009 H1 หน้าแรก + แก้ H1 ซ้อน • #011 ถอด translate='no' • — ห้ามใส่งาน off-site ใน phase นี้ — |
• #002 ใส่เมนูจริง + ราคา + Menu schema • #005 Restaurant schema + sameAs • #008 OG tag + twitter:card • #010 ประกาศที่อยู่ + อีเมล • #012 alt text 79 จุด (28 ไฟล์) • #013 แกลเลอรี่ CSS background → <img> • #014 BreadcrumbList + WebSite schema • #015 FAQ จริง 6 ข้อ + FAQPage • OS-1 แก้ NAP + แจ้ง Wongnai แก้ชื่อ |
• #016 BlogPosting schema + dateModified • #017 แก้ slug บทความ 2 บท + 301 • #018 preload วิดีโอ 42.8 MB • #019 นโยบายแคช + cache-bust • #020 noindex subdomain web. • #021 ลิงก์ YouTube + รวม IG • #022 lazy load + WebP • #023 nav ซ้ำ 3 ชุด + javascript: links • #024 เขียนบทความใหม่ 5 บท • OS-2 อัปคลิป YouTube ใหม่ • OS-3 ถึง OS-6 งานสะสม authority |
10 Score Ceiling Note ทำไมคาดหวังที่ 88 ไม่ใช่ 85+
|
เพดานคะแนนที่ประเมินไว้: 88/100 (เกรด A — AI-Ready) ตัวเลขนี้คือคะแนนหลังทำ ticket ครบทุกใบและงาน off-site ถูก index แล้ว ไม่ใช่ค่าที่รับประกัน |
เพดาน 88 สูงกว่าลูกค้าทั่วไปมาก และเหตุผลอยู่นอกเว็บ
เว็บส่วนใหญ่ที่เริ่มต้นที่เกรด D จะไปได้ไกลสุดราว 75 ถึง 80 แต่เคสนี้ต่างออกไป เพราะสองมิติที่แพงที่สุดและสร้างยากที่สุดคือ AI Citation Presence กับ Off-Site Presence แข็งอยู่แล้วตั้งแต่ก่อนเริ่มงาน โดยได้ 85 และ 90 ตามลำดับ ซึ่งมาจาก Google Business Profile ที่มีรีวิวกว่า 1,800 รายการ รางวัลระดับสากล 3 รายการ และสื่อออกแบบต่างประเทศที่เขียนถึงเอง ทุนก้อนนี้ไม่มีทางลัดสร้างได้ และแบรนด์นี้มีอยู่แล้ว งาน WebFix ชุดนี้จึงไม่ใช่การสร้างชื่อเสียงใหม่ แต่คือการทำให้เว็บของตัวเองเลิกเป็นคอขวดของชื่อเสียงที่มีอยู่
HTML ratio 0.232 จะยังค้างอยู่ที่ 30 คะแนน
ค่านี้ต่ำเพราะหน้ามี inline style block และ inline script ขนาดใหญ่ ไม่ใช่เพราะเป็น SPA ซึ่งต่างจากเคส WordPress ที่ page builder ทำ HTML บวม การจะดันให้ถึงเกณฑ์ 0.5 ที่ให้คะแนนเต็มต้องย้าย CSS และ JS ทั้งหมดออกไปเป็นไฟล์นอก ซึ่งทำได้จริงและไม่ยากสำหรับเว็บ PHP ล้วนแบบนี้ แต่ไม่ได้อยู่ใน ticket ชุดนี้เพราะได้คะแนนกลับมาเพียง 2.1 คะแนนขณะที่เสี่ยงทำหน้าพัง ถ้าทำเพิ่มภายหลังเพดานจะขยับจาก 88 เป็นประมาณ 90
AI Citation ค้างที่ 85 จนกว่าจะมี Wikipedia หรือ Wikidata
มิตินี้ขาดอยู่ 15 คะแนนสุดท้ายซึ่งมาจาก Wikipedia หรือ Wikidata entry เท่านั้น การแก้โค้ดทุก ticket ในเอกสารนี้ไม่ช่วยส่วนนี้เลยแม้แต่คะแนนเดียว แต่ต่างจากลูกค้าทั่วไปตรงที่แบรนด์นี้มีคุณสมบัติเอื้อมถึงได้จริง เพราะมีรางวัลระดับสากลที่ตรวจสอบได้ 3 รายการ มีสื่อนานาชาติเขียนถึง และมีสถาปนิกผู้ก่อตั้งที่มีชื่อเสียงระดับโลก ถ้า OS-5 สำเร็จ เพดานจะขยับจาก 88 เป็นประมาณ 92 ซึ่งเป็นเกรด A เต็มตัว
ticket #002 เรื่องเมนูคือตัวแปรเดียวที่ใหญ่ที่สุด
ถ้าทำ ticket อื่นครบทุกใบแต่ไม่ทำ #002 คะแนนจะไปได้ไกลสุดราว 80 เท่านั้น เพราะ #002 เป็นใบเดียวที่ปลดค่าปรับ thin content 15 คะแนน และยกระดับ Snippet Readiness จาก 10 เป็น 70 พร้อมกัน ที่สำคัญกว่าคะแนนคือผลทางธุรกิจ วันนี้เมื่อมีคนถาม AI ว่าร้านนี้ราคาเท่าไร คำตอบมาจาก Wongnai ไม่ใช่จากเว็บร้าน ซึ่งแปลว่าแบรนด์ไม่ได้ควบคุมข้อมูลราคาของตัวเอง งานนี้ติดอยู่ที่ต้องขอไฟล์เมนูฉบับจริงจากลูกค้าก่อน จึงควรขอตั้งแต่วันแรกที่เริ่มโครงการ
งาน off-site รอบนี้เป็นการรักษา ไม่ใช่การสร้าง
ต่างจากลูกค้าเกือบทุกรายที่ต้องไปสร้าง Google Business Profile และหา listing ใหม่ แบรนด์นี้มี 6 จาก 8 ช่องได้เต็ม 10 อยู่แล้ว งาน off-site ทั้งหมดจึงเหลือแค่ OS-1 คือแก้ NAP ให้ตรงกันเพื่อปลดค่าปรับ 10 คะแนน กับ OS-6 คือรักษาช่องที่ได้เต็มไม่ให้ตก ส่วน OS-3 LinkedIn และ OS-4 Pantip ไม่เพิ่มคะแนนเลยเพราะคะแนนคิดจาก best 5 of 8 ต้องบอกลูกค้าให้ชัดว่าอย่าเสียแรงกับสองช่องนี้ถ้าไม่มีเหตุผลทางธุรกิจอื่นรองรับ
ความต่างระหว่างแก้โค้ดกับสะสม authority
ticket #001 ถึง #024 คืองานแก้โค้ดที่ให้ผลค่อนข้างแน่นอนและวัดได้ทันทีหลังแก้ ส่วน OS-1 ถึง OS-6 คือการสะสมความน่าเชื่อถือซึ่งไม่มีทางลัด แต่กรณีนี้กลับกันกับที่เจอปกติ คือฝั่ง authority ทำเสร็จไปแล้วโดยธรรมชาติของธุรกิจ ส่วนฝั่งโค้ดต่างหากที่ยังไม่ได้ทำ ซึ่งเป็นข่าวดี เพราะงานโค้ดควบคุมได้ มีกำหนดเสร็จชัดเจน และวัดผลได้ในรอบ re-audit ถัดไป
ข้อควรระวังเรื่องการเทียบคะแนนตอน re-audit
|
รายงานฉบับนี้คือ baseline แรกของโดเมนนี้ ไม่มี audit เก่าให้เทียบ จึงไม่มีปัญหาเรื่องคนละสูตรเหมือนลูกค้ารายอื่น · สิ่งที่ต้องระวังตอน re-audit มี 3 ข้อ หนึ่ง ต้องใช้สูตร v2.0 เท่านั้นตามที่ pin ไว้ใน VERSIONS.md ห้ามเปลี่ยนกลางทาง สอง คะแนน Page Speed รอบนี้วัดเองด้วย Lighthouse 13.4.1 บน headless Chrome ฝั่งละ 3 รอบแล้วเอาค่ามัธยฐาน เพราะ PageSpeed Insights API ตอบ HTTP 429 โควตารายวันหมด รอบ re-audit ต้องใช้วิธีเดียวกันนี้ ไม่ใช่ค่าจาก API ไม่งั้นตัวเลขจะเทียบกันไม่ได้ สาม การตัดสิน Schema.org ใน 5B รอบนี้ให้ 20 เต็มตามกติกาแบบมี-ไม่มี เพราะพบ JSON-LD จริงและยิงจาก server-side แม้จะครอบคลุมแค่ 1 ใน 15 หน้าและเป็น VideoObject ที่ไม่ใช่ประเภทหลักของธุรกิจ ต้องใช้กฎเดียวกันนี้ตอน re-audit |