# รายงานส่งมอบการต่อยอด 485Tech

**โครงการ:** 485Tech Free Online Tools Platform  
**ขอบเขต:** ยกระดับแพลตฟอร์ม free tools, ติดตั้ง AdSense framework, เพิ่ม portability/PWA/discovery และตรวจความพร้อมก่อน deploy  
**สถานะ:** พัฒนาและทดสอบแล้ว; implementation ถูก push ขึ้น GitHub แล้ว แต่ยังไม่ได้ deploy production ด้วยตัว agent

> **หมายเหตุสำคัญ:** ส่วน privacy/consent และ AdSense ในเอกสารนี้เป็น working implementation และ working draft สำหรับใช้งานจริงในระบบ แต่ไม่ใช่คำแนะนำทางกฎหมาย ผู้อดูแลเว็บไซต์ควรให้ผู้เชี่ยวชาญตรวจเนื้อหาให้เหมาะกับธุรกิจ เขตอำนาจศาล และวิธีเก็บข้อมูลจริงก่อนเผยแพร่

## 1. สรุปผลการพัฒนา

รอบนี้เปลี่ยน 485Tech จากเครื่องมือรวมหลายรายการให้มีลักษณะเป็นแพลตฟอร์มมากขึ้น โดยยังรักษาหลักการ **local-first** คือให้เครื่องมือที่ทำได้ใน browser ประมวลผลบนอุปกรณ์ของผู้ใช้ และไม่ส่ง input ของผู้ใช้ขึ้นเซิร์ฟเวอร์โดยอัตโนมัติ ปัจจุบัน catalog มีเครื่องมือพร้อมใช้งาน 159 รายการ และมีทั้งชั้นการค้นหาแบบ use-case กับหน้า SEO ที่ช่วยให้ผู้ใช้เริ่มจากงานที่ต้องการได้โดยไม่จำเป็นต้องรู้ชื่อเครื่องมือก่อน

| พื้นที่ | สิ่งที่เพิ่มหรือปรับ | สถานะ |
|---|---|---|
| Discovery | Use-case collections: พัฒนาเว็บ, ข้อความและคอนเทนต์, ไฟล์และ PDF, รูปภาพและสื่อ, ความปลอดภัย, ข้อมูลและตาราง | ทำแล้ว |
| Preferences | Export/import JSON ของ pins, recent history และ sort preference พร้อม version validation | ทำแล้ว |
| Portability | PWA manifest และ service worker ที่ cache เฉพาะ static assets ไม่ cache HTML nonce หรือข้อมูลผู้ใช้ | ทำแล้ว |
| AdSense | Consent-gated loader, Auto Ads support, non-personalized default, provider deduplication และ persistent privacy settings | ทำแล้ว |
| Publisher setup | `google-adsense-account` metadata และ `public/ads.txt` | ทำแล้ว |
| Privacy | Disclosure ของ Google AdSense, link ไป Google partner-site explanation และปุ่มจัดการการตั้งค่าโฆษณา | ทำแล้ว; ควร review ก่อนเผยแพร่ |
| Security | เพิ่ม CSP origins สำหรับ AdSense และตรวจ blob image/worker ที่ Background Remover ใช้ | ทำแล้ว |
| QA | เพิ่ม UI regression checks ของ consent, collections, PWA, export/import, batch และ SEO routes | ทำแล้ว |
| GitHub delivery | Push implementation `3f1adcc` และ roadmap `2ea5acc` ขึ้น `main`; remote ตรงและ working tree สะอาด | ทำแล้ว |
| Pipeline verification | ตรวจ Workers Builds/Pages API และ live routes หลัง push | พบ blocker: ยังไม่พบ build config และ live route ใหม่ตอบ 1101 |
| Batch workflow | เพิ่ม Batch Text Toolkit: multi-file queue, trim/dedupe/sort/case, preview, retry/skip, cancel และ ZIP export | ทำแล้ว; local-only |
| SEO/content | เพิ่ม `/use-cases`, canonical URLs, CollectionPage JSON-LD และ auto-generated `/sitemap.xml` | ทำแล้ว |

## 2. AdSense implementation ที่ติดตั้งแล้ว

ระบบใช้ publisher ID `ca-pub-6341158024893936` ซึ่งพบอยู่ใน source เดิมและมีที่มาจาก commit ใน repository ก่อนรอบนี้ จึงนำมาใช้ต่อใน metadata และ `ads.txt` โดยไม่สร้างค่า placeholder ใหม่ ไฟล์ `public/ads.txt` ใช้รูปแบบ `google.com, pub-6341158024893936, DIRECT, f08c47fec0942fa0` และถูกทดสอบผ่าน worker fixture ว่าสามารถตอบกลับจาก root route ได้

AdSense loader ใน `public/scripts/ads.js` จะไม่โหลด provider script จนกว่าผู้ใช้จะเลือกอนุญาตโฆษณา หากยังไม่มีคำตอบจะซ่อน ad slot และไม่สร้าง request ไปยัง Google หากผู้ใช้ปฏิเสธจะเก็บสถานะ `denied` และซ่อน slot หากผู้ใช้ยอมรับจะโหลด provider เพียงครั้งเดียว เริ่ม Auto Ads และตั้ง `requestNonPersonalizedAds=1` เป็นค่าเริ่มต้น วิธีนี้ทำให้ browser flow ทำงานจริง แต่การแสดงโฆษณาบน production ยังขึ้นกับการยืนยันไซต์ การ review และการตั้งค่าในบัญชี AdSense ของเจ้าของเว็บไซต์

> Google ระบุว่า AdSense ไม่อนุญาตการจัดวางที่ทำให้ผู้ใช้เข้าใจว่าโฆษณาเป็นเมนู ปุ่มดาวน์โหลด หรือ navigation และห้ามการชักจูงให้คลิกโฆษณา [1] [2]

โค้ดรองรับ manual ad slot ในอนาคตผ่าน `AD_CONFIG.slots` แต่จงใจปล่อย map นี้ว่างไว้ เพราะ slot ID ต้องมาจาก ad units จริงในบัญชี ห้ามใส่เลขเดา การใช้ Auto Ads ตอนนี้จึงเป็นเส้นทางที่ไม่สร้าง ad unit ปลอม และพื้นที่ `.ad-slot` จะถูกซ่อนเมื่อไม่มี manual slot ID

## 3. Consent, privacy และข้อจำกัดที่ต้องทำในบัญชี

ระบบมี application-level consent manager พร้อมลิงก์เปิดการตั้งค่าใหม่จาก footer และหน้า privacy แต่ banner ที่สร้างใน repository นี้ **ไม่ควรถูกอ้างว่าเป็น Google-certified CMP** เมื่อจะเปิด personalized ads สำหรับผู้ใช้ใน EEA, UK หรือ Switzerland ควรสร้างและ publish ข้อความผ่าน Google Privacy & Messaging หรือใช้ CMP ที่ Google รับรองและเชื่อมกับ IAB TCF ตามข้อกำหนดของ Google [3] [4]

ตอนนี้จึงตั้งค่า non-personalized ads เป็นค่าเริ่มต้นเพื่อไม่เปิด personalized targeting จาก source โดยตรง ผู้ดูแลระบบควรทำตามลำดับต่อไปนี้ก่อนเปิดใช้งาน production:

| ขั้นตอน | สิ่งที่ต้องทำ | ผู้รับผิดชอบ |
|---:|---|---|
| 1 | ตรวจว่า `ca-pub-6341158024893936` เป็น publisher ID ของบัญชีเว็บไซต์นี้จริง | เจ้าของ AdSense |
| 2 | เพิ่ม `485tech.com` ใน AdSense และวาง verification/รอ site review | เจ้าของ AdSense |
| 3 | เปิด Auto Ads หรือสร้าง manual units ในบัญชี แล้วใส่ slot ID จริงเฉพาะตำแหน่งที่ต้องการ | เจ้าของ AdSense + ผู้พัฒนา |
| 4 | ตั้ง Privacy & Messaging สำหรับ EEA/UK/Switzerland และตรวจ CMP requirement | เจ้าของ AdSense |
| 5 | Deploy แล้วตรวจ `https://485tech.com/ads.txt`, ad request, CSP reports และ layout จริง | ผู้พัฒนา |
| 6 | หลังมี report เพียงพอ ค่อยพิจารณาเปลี่ยน CSP จาก Report-Only เป็น Enforce | ผู้ดูแล security |

Google ระบุว่า strict CSP ที่ใช้ nonce และ `strict-dynamic` เป็นแนวทางที่รองรับกับ AdSense และแนะนำให้ทดสอบด้วย Report-Only ก่อน enforce [5] เว็บไซต์จึงยังคง `CSP_MODE=report-only` บน Worker production เพื่อหลีกเลี่ยงการบล็อก legitimate provider request โดยไม่เห็นข้อมูลจริงก่อน

## 4. ฟีเจอร์ต่อยอดที่พร้อมใช้

### 4.1 Use-case collections

Tools Hub มี collection bar ที่กรองเครื่องมือหลายหมวดพร้อมกัน ตัวอย่างเช่น collection “พัฒนาเว็บ” กรองเหลือ 10 เครื่องมือ developer และปรับ category counts ตามผลลัพธ์จริง ทำให้หน้ารวม 159 รายการไม่รู้สึกเป็นเพียงรายการยาว ๆ และตอนนี้มีหน้า `/use-cases` เป็น landing/discovery layer ที่เปิด collection เหล่านี้ได้โดยตรง

### 4.2 Export/import local preferences

ผู้ใช้สามารถส่งออก pins, recent tools และ sort preference เป็น `485tech-tools-settings.json` แล้วนำเข้าอีกอุปกรณ์หนึ่งได้ ไฟล์มี `version` และ `product` marker ระบบจะ reject ไฟล์ที่ product ไม่ตรงหรือ version ไม่รองรับ และจะเขียนข้อมูลกลับผ่าน `Tools.pins.replace` กับ `Tools.history.replace` เท่านั้น ไม่มี tool input, account token หรือข้อมูลลับอยู่ในไฟล์นี้

### 4.3 Installable app shell

เพิ่ม `manifest.webmanifest` ให้เปิดแอปเริ่มต้นที่ `/tools` และเพิ่ม `sw.js` สำหรับ cache static assets เท่านั้น Service worker ไม่ cache HTML เพื่อไม่ทำให้ response ที่มี per-request CSP nonce ค้างอยู่ และไม่ cache API response หรือข้อมูลจาก tool ผู้ใช้จึงได้ประโยชน์ด้านความเร็วและการติดตั้งโดยไม่ลด security boundary ของ Worker

### 4.4 Batch Text Toolkit

เพิ่ม `/tools/batch-text` เป็น workflow local-first สำหรับไฟล์ข้อความหลายไฟล์ โดยรองรับ drag-and-drop, file picker, extension validation, per-file 5 MB limit, trim whitespace, deduplicate lines, sort, case conversion, suffix, preview, retry/skip และ cancel หลังจบรอบไฟล์ปัจจุบัน ผลลัพธ์คงนามสกุลเดิม, ดาวน์โหลดแยกได้ และรวมเป็น ZIP ด้วย fflate ที่ vendored อยู่ใน repository; ไม่มีการส่งไฟล์ไป server

### 4.5 Use-case SEO content layer

เพิ่ม `/use-cases` เป็นหน้า discovery ที่มี 6 collection cards เชื่อมตรงไปยัง query ที่ Tools Hub รองรับ ได้แก่ developer, content, files, images, security และ data เพิ่ม canonical URL ใน public pages และ standalone tools, CollectionPage JSON-LD และให้ build สร้าง `sitemap.xml` อัตโนมัติจาก public pages กับ live tool routes รวม 167 URLs การทำงานนี้เป็น static build output และไม่เพิ่มข้อมูลผู้ใช้ลงใน URL

## 5. ผลการทดสอบ

ชุดตรวจล่าสุดผ่านทั้งหมด โดยมีทั้งการตรวจ syntax, generated catalog, browser interaction, file processing และ Worker security behavior

| ชุดทดสอบ | ผลลัพธ์ |
|---|---:|
| Build | ผ่าน; generated 8 public pages, 159 standalone pages และ sitemap 167 URLs |
| Catalog validation | ผ่าน; 159 catalog / 159 live / 0 failures |
| Smoke test เครื่องมือทั้งหมด | ผ่าน 159/159 |
| Functional audit PDF, Office, ZIP, image และ audio | ผ่าน 19/19 |
| UI regression desktop/mobile | ผ่าน 40/40 รวม batch cancel, use-case SEO และ mobile overflow coverage |
| Worker security and route smoke | ผ่าน 54/54 รวม `/use-cases` และ `/sitemap.xml` |
| `node --check` สำหรับ JS ที่แก้ | ผ่าน |
| `git diff --check` | ผ่าน |

Browser validation ยืนยันว่าเมื่อยังไม่มี consent จะพบ `consent=null`, banner แสดง, provider script ยังไม่ถูกโหลด และ ad slot มีสถานะ `consent-pending`; หลัง allow provider script ถูกโหลดและ queue มี request; หลัง deny สถานะถูกบันทึกเป็น `denied` และ slot ถูกซ่อน การทดสอบใน localhost ไม่สามารถยืนยันว่าบัญชี Google จะ serve ad จริง เพราะ origin local ไม่ใช่ production ที่ผ่านการอนุมัติ

## 6. สถานะ Cloudflare และ GitHub

ตรวจ Cloudflare Worker production resource ชื่อ `home` แบบ read-only สำเร็จ โดยมี ASSETS binding, `CSP_MODE=report-only`, HSTS max-age 86400 และ includeSubDomains การ deployment ล่าสุดที่ API รายงานสร้างเมื่อ 22 สิงหาคม 2026 และยังไม่สะท้อน source commit `3f1adcc`/`2ea5acc` รอบนี้

หลัง push ตรวจเพิ่มแล้ว Cloudflare API ไม่พบ Workers Builds configuration ของ `home` และไม่พบ Pages project ใน account ที่ตรวจ ขณะเดียวกัน live route ใหม่ `/use-cases`, `/sitemap.xml`, `/tools/batch-text`, `/ads.txt` และ `/manifest.webmanifest` ตอบ `500 error code: 1101` ในช่วงตรวจ จึงต้องถือว่า GitHub-to-Cloudflare pipeline เป็น release blocker และต้องยืนยัน/แก้ใน Cloudflare dashboard ก่อนประกาศ production release การตรวจนี้ไม่ได้เปลี่ยน binding หรือ deploy เพราะผู้ใช้อนุญาตเฉพาะการ push GitHub และระบุว่า Cloudflare จะ build เอง

การ deploy รอบถัดไปควรเริ่มจากตรวจ source of truth ของ build, ยืนยัน publisher ID และตั้งค่า AdSense account ให้เสร็จก่อน จากนั้นตรวจ live routes และ rollback path

## 7. Roadmap ต่อไปเพื่อให้เป็น free tools platform เต็มระบบ

| ระยะ | ฟีเจอร์ | เหตุผลที่ควรทำ |
|---|---|---|
| P0 | Tool collections เป็น URL landing pages | เพิ่ม SEO และลดเวลาจาก search ไปถึงงานที่ต้องการ |
| P0 | IndexedDB workspace | กลับมาทำงานต่อได้โดยไม่ส่งข้อมูลขึ้น server |
| P0 | Batch queue + retry/cancel + ZIP export | ทำงานกับไฟล์หลายรายการแบบมืออาชีพ |
| P0 | Capability badges | บอกชัดว่า offline, client-side, file type, limit และต้องใช้ network หรือไม่ |
| P1 | Command palette `Ctrl/Cmd+K` | รองรับผู้ใช้ power user และเปิด tool ได้เร็ว |
| P1 | Shareable recipes | แชร์ลำดับงานโดยเก็บเฉพาะ configuration ไม่เก็บข้อมูลลับ |
| P1 | Offline capability report | บอกก่อนเปิดว่าฟีเจอร์ใดใช้ได้เมื่อไม่มีอินเทอร์เน็ต |
| P1 | Accessibility center | เพิ่ม font scale, contrast, reduced motion และ keyboard map |
| P1 | SEO guides/FAQ ต่อหมวด | สร้าง organic traffic ที่ไม่พึ่งโฆษณาอย่างเดียว |
| P2 | Optional encrypted account sync | ย้าย workspace ข้ามอุปกรณ์โดยเป็น opt-in |
| P2 | Deterministic public API | เปิด conversion API บางประเภทพร้อม rate limit และ schema versioning |
| P2 | Privacy-first aggregate analytics | วัดความนิยมโดยไม่เก็บ input และมี retention limit |

## 8. ไฟล์สำคัญที่แก้หรือเพิ่ม

| ไฟล์ | หน้าที่ |
|---|---|
| `public/scripts/ads.js` | Consent-gated AdSense loader และ Auto Ads behavior |
| `src/layout.html`, `src/app-layout.html` | AdSense metadata/config และ manifest link |
| `public/ads.txt` | Authorized seller declaration |
| `src/pages/privacy.html` | AdSense disclosure และ privacy settings control |
| `wrangler.toml`, `src/worker/index.js` | AdSense CSP origins และ blob support |
| `public/scripts/tools/apps/batch-text/*` | Multi-file local text workflow, transformations, cancel/retry/skip และ ZIP export |
| `src/pages/use-cases.html`, `public/styles/pages.css` | Use-case SEO discovery page และ responsive visual system |
| `scripts/build.mjs`, `public/sitemap.xml` | Canonical replacement และ auto-generated sitemap |
| `docs/visual-qa-use-cases.md` | ผล visual QA ของหน้า use-case |
| `public/manifest.webmanifest`, `public/sw.js` | Installable app shell และ static cache |
| `public/scripts/tools/tools-core.js` | replace APIs สำหรับ local preferences |
| `public/scripts/tools/tools-hub.js`, `src/pages/tools.html` | collections และ export/import preferences |
| `src/i18n/th.json`, `src/i18n/en.json`, `public/scripts/app.js` | ข้อความสองภาษาและ fallback dictionary |
| `scripts/ui-regression.mjs`, `scripts/worker-smoke.mjs` | automated regression coverage |
| `docs/adsense-research.md`, `docs/platform-roadmap.md` | ข้อกำหนดอ้างอิงและ roadmap |

## References

[1]: https://support.google.com/adsense/answer/48182?hl=en "AdSense Program policies"
[2]: https://support.google.com/adsense/answer/1346295?hl=en "Ad placement policies"
[3]: https://support.google.com/adsense/answer/16918505?hl=en "How the Google Consent Management Platform works"
[4]: https://support.google.com/adsense/answer/7670013?hl=en "Set up and manage your Consent Management Platform"
[5]: https://support.google.com/adsense/answer/16283098?hl=en "Integrate the AdSense ad code with a Content Security Policy"
