AVADA · TS ELITE
Training nội bộ · Accessibility DFY

Buổi 2:
Đi sâu — cách check & fix

TS làm được tay — chạy scan, inspect từng lỗi critical (đặc biệt H1 & alt), fix app-side/theme-side đúng cách có guardrail, và verify Phase 4 trước khi báo "fixed".

Scan + inspect Fix theme (guardrail) Phase 4 verify
Flow chi tiết · LIVE trong extension

Chạy scan & đọc output

Ở đâu

Panel Tools trong extension → chọn "♿ Accessibility — DFY Scan". Ô store tự điền từ conversation Crisp đang mở.

Tuỳ chọn trước khi bấm Scan

Bật Auto-discover pages từ sitemap.xml, đặt Số trang tối đa (mặc định 10), hoặc dán danh sách URL (mỗi dòng 1 URL) — có URL thì bỏ qua auto-discover.

Kết quả

Report HTML gộp: tổng quan (số trang, điểm tệ nhất, điểm trung bình, tổng lỗi) rồi từng trang — trang tệ nhất lên đầu, mỗi trang có điểm + verdict WCAG + lỗi nhóm theo severity.

Store khoá password:

  • Store gated thì /sitemap.xml trả 404 → auto-discover không ra gì.
  • Tool tự động lùi về scan đúng trang đã nhập, và ghi chú việc này trong report.
  • Muốn auto-discover chạy được trên store khoá → điền ô Store password.
Scan nhiều trang

Elite vs DevZone "Test Scan"

Elite (Tool Runner)

  • Quét nhiều trang là thật, không phải giả lập — nhưng API chặn cứng tối đa 10 URL/lần (gửi 11 → lỗi "Too many urls — max 10 per request").
  • Cần >10 trang → chia đợt, chạy nhiều lần.
  • Dùng cho: quét nhanh vài trang trọng điểm khi hỗ trợ 1 case.

DevZone "Test Scan"

  • Quét toàn bộ store → phải vào DevZone app Accessibility, không làm được từ Elite.
  • Cần phiên đăng nhập admin nhúng của Shopify → chỉ chạy khi có người đăng nhập DevZone.
  • Liệt kê trang bằng Shopify Admin API (toàn bộ product/collection/page/article), không đọc sitemap, rồi chia lô 10 trang quét song song.
Ghi nhớ: Elite = quét nhanh vài trang trọng điểm. DevZone Test Scan = quét cả store.
Lọc false-positive

Chạy manual test, đừng tin heuristic

  • !2.2.6 (Timeouts): add-to-cart + điền form dở, chờ 15-20 phút → có auto-logout/hết hạn không? Không → mark Done.
  • !3.2.1 (On Focus): Tab qua trang / click field → có auto-navigate/auto-submit không? Không → nhiễu.
  • !3.3.4 (confirm): form flag có xử lý dữ liệu legal/financial thật không? Checkout Shopify đã có review sẵn; newsletter/contact không phải legal/financial → mark Done.

Mark as Solved

Chỉ merchant tự tick. TS/CS không tick hộ. Chỉ dùng sau khi (a) khách đã fix ngoài app và TS verify storefront, hoặc (b) TS chạy manual test cùng khách và xác nhận không phải lỗi thật. Không dùng để làm đẹp điểm.

★ Inspect critical #1 · WCAG 1.3.1

Heading / H1

Trang không có H1, hoặc nhảy cấp (H2 → H4). Scanner chỉ báo jump đầu tiên tìm thấy → fix xong re-scan có thể lộ jump tiếp theo.

// Liệt kê heading theo thứ tự DOM
console.table([...document.querySelectorAll('h1,h2,h3,h4,h5,h6')]
  .map(h => ({ level: h.tagName, text: h.textContent.trim().slice(0, 70) })));

// Đếm số H1 (phải = 1)
document.querySelectorAll('h1').length;

Đúng: đúng một H1, các cấp sau không nhảy quá 1 bậc (H1→H2→H3, không H2→H4). Nhanh hơn: dùng feature Page Structure trong widget.

Fix nhóm E
  • Nội dung Page/Blog: rich text editor → đổi format (Heading N).
  • Theme: Customize tìm setting "Heading size/level"; không có thì Edit code sửa Liquid <h4>→<h3>.
  • Duplicate theme trước.
★ Inspect critical #2 · WCAG 1.1.1

Alt text

Ảnh thiếu alt (screen reader không đọc được), hoặc empty-alt (logo/icon/banner bị đánh dấu trang trí sai).

// Ảnh thiếu alt hoặc alt rỗng
[...document.querySelectorAll('img')]
  .filter(i => !i.hasAttribute('alt') || i.alt.trim() === '')
  .map(i => i.currentSrc || i.src);
  • Fix thủ công (bền): Admin → Content → Files → Alt text; sản phẩm: Products → Media → Edit alt text; bulk qua CSV.
  • Bật AI Alt Text cần cả 3 điều kiện: Scale plan, toggle enableAutoAltText ON, app cài sau 2025-06-17 23:59 Bangkok.

Caveat CỰC QUAN TRỌNG

Alt AI sinh runtime, client-side, chỉ xuất hiện khi visitor bật Text-to-Speech trong widget. Không lưu ngược vào product data Shopify (app không có scope write_products). Điểm được cộng ngay khi bật toggle, trước khi thực sự có alt nào. Muốn alt trong data thật (SEO / tool 3rd-party) → phải nhập tay ở Admin.

Inspect critical #3 · WCAG 4.1.2

Accessible name

Nút/link tương tác (thường icon-only: giỏ hàng, search, hamburger, social) không có tên → screen reader chỉ đọc "button".

[...document.querySelectorAll('a,button,input,select,textarea,[role="button"],[role="link"]')]
  .filter(el => !el.getAttribute('aria-label') && !el.getAttribute('aria-labelledby')
    && !el.textContent.trim() && !el.title && !el.value && el.offsetParent !== null)
  .map(el => el.outerHTML.slice(0, 120));
Fix nhóm E, theme

Thêm đúng một aria-label="..." bằng ngôn ngữ store (vd "Cart", "Search", "Open menu", "Facebook"). Tìm class trong sections/header.liquid, snippets/ qua Edit code. Duplicate theme trước.

Đính chính: tooltip "Auto Alt Text" trong app ghi kèm "and accessible name" nhưng AI KHÔNG thực sự sinh accessible name — không có code backing việc này. 4.1.2 vẫn phải fix tay trong theme, đừng trông chờ AI lo hộ.
Inspect các critical còn lại

2.4.11 · 3.3.4 · 3.3.8

Overlay/focus

2.4.11

  • Nhấn Tab liên tục khi có sticky header/popup/drawer mở — focus có bị che hoàn toàn không?
  • Fix: focus trap (tabindex="-1" + .focus() khi mở, Esc đóng, trả focus về trigger) — thường dev/theme.
Confirm step

3.3.4

  • Form bị flag có phải legal/financial thật?
  • Có → thêm bước review hoặc checkbox required; không → mark Done.
Auth khó

3.3.8

  • Ô password gần text yêu cầu phức tạp.
  • Fix: thêm "Show password" toggle, hoặc chuyển Shopify Customer Accounts (new) OTP/magic-link — no code.
Fix theme-side (nhóm E) · điểm KPI cao nhất

TS FIX THẬT — có GUARDRAIL

  • 1Xin collaborator access đúng scope (Apps/Themes, không "All"); xong nhắc khách revoke.
  • 2Duplicate theme TRƯỚC khi sửa (Online Store → Themes → ⋯ → Duplicate). Hỏng → publish bản copy khôi phục.
  • 3Sửa đúng recipe (xem card bên) rồi verify Phase 4 mới báo fixed.

Snippet mẫu:

  • lang thiếu (3.1.1): <html lang="{{ request.locale.iso_code }}"> trong layout/theme.liquid
  • title thiếu (2.4.2): <title>{{ page_title }} | {{ shop.name }}</title>
  • duplicate-id (4.1.1): id="section-{{ forloop.index }}" trong loop
  • aria-label (4.1.2 / 3.3.2): thêm vào nút/input
  • heading (1.3.1): sửa cấp thẻ h
★ Phase 4 — Verify checklist

Gate BẮT BUỘC trước khi báo "đã fix"

  • 1Embed ON trên theme published (Theme editor → App embeds). Nếu OFF: điểm A/B vẫn cộng nhưng storefront không chạy gì — trạng thái nguy hiểm nhất.
  • 2Re-scan đúng URL đó (issue list bị thay mới hoàn toàn; markAsSolved giữ qua re-scan).
  • 3Đối chiếu điểm theo công thức critical −10 / moderate −5 / minor −1 (sàn 20). Nhóm A/B phải có solvedBySea: true.
  • 4Kiểm tra thủ công trên storefront thật (tab ẩn danh): nhóm A widget popup mở; nhóm B TTS đọc alt mới; nhóm E view-source lang/title/heading/aria-label.
Tool & escalate

"A11y Inspect" (sắp có) · khi nào escalate

"A11y Inspect" — CHƯA phát hành

Code đã viết xong nhưng chưa ship kèm extension — đừng hứa TS dùng được ngay. Khi ra mắt, nút "A11y Inspect" sẽ cho kiểm tra nhanh ngay trên tab storefront đang mở: 1 click → ra 3 danh sách (heading outline/H1, ảnh thiếu alt, phần tử thiếu accessible name) và highlight trực tiếp trên trang. Hiện tại vẫn dùng scan trong Tools panel + snippet console.

Escalate & disclaimer

  • App bug (429, scan stuck, điểm sai công thức) → fast-path escalate dev + log. KHÔNG dùng escalate để né việc fix nhóm E.
  • Legal document (demand letter, đòi chứng nhận) → escalate BA/PM ngay.
  • Mọi phản hồi điểm/rủi ro → kèm disclaimer: không phải cam kết pháp lý.
Recap buổi 2

Đã đủ tay nghề
check & fix a11y critical

  • 1Scan → đọc locations → lọc false-positive bằng manual test.
  • 2Inspect critical bằng snippet console: H1, alt, accessible name.
  • 3Alt AI = runtime-only, không lưu product data — phải nói rõ khách.
  • 4Nhóm E = TS fix thật trong theme, guardrail (duplicate theme trước) — KPI cao nhất.
  • 5Phase 4 verify là gate: embed ON + re-scan + đối chiếu điểm + kiểm tra storefront thật.
  • 6App bug → dev; legal doc → BA/PM; luôn kèm disclaimer.
TS fix thật, có guardrail Không cấp legal cert
Tra cứu

PHẦN III
Cẩm nang fix từng lỗi

Bám source code · verified GitLab 62815476 master
App tính điểm thế nào

Công thức & 3 nhóm xử lý

SEVERITY_SCORES = { critical: 10, moderate: 5, minor: 1 };
finalScore = Math.max(20, Math.min(100, 100 - totalScore));
lawsuitRisk = finalScore >= 90 ? 'Low' : 'High';
NhómCơ chếTS làm gì
① AUTO solvedBySea1.4.11, 2.4.11, 2.5.8, 3.3.2 — app credit vô điều kiệnKhông cần fix cho điểm
② AI-credit1.1.1, 4.1.2, 4.1.3 — credit khi bật AI alt-textBật feature nếu đủ điều kiện, else fix thật
③ Phải fix thậtCòn lại đang scanTS vào theme/admin fix thật (guardrail)
Bảng ưu tiên fix

Shop chưa bật AI alt-text

Ưu tiênWCAGĐiểm/lỗiVì sao
🔴 11.3.1, 3.3.4, 3.3.8+10Critical, luôn phải fix thật
🔴 21.1.1, 4.1.2+10Critical — bật AI thì credit, else fix thật
🟡 32.4.2, 3.1.1, 3.2.1, 3.2.2, 4.1.3+1Minor, fix nhanh trong theme
⚪ bỏ1.4.11, 2.4.11, 2.5.8, 3.3.20Auto-solved, không trừ điểm
⚪ bỏ4.1.10Checker disabled, không scan
1.3.1 / 3.3.4 / 3.3.8 = fix xong mỗi lỗi giảm hẳn 10 điểm — ưu tiên số 1.
Critical

Cách fix

WCAGCheckerAccessFix
1.3.1checkBasicAccessibility :250,263,290Pages / ThemesĐúng 1 H1, sửa cấp heading trong content/theme
3.3.4checkErrorPrevention :1340ThemesThêm bước review/confirm; N/A → markAsSolved
3.3.8checkAccessibleAuthentication :1554Themes / SettingsShow-password toggle hoặc Customer Accounts OTP
1.1.1checkBasicAccessibility :81,93,135App AI / ContentBật AI alt-text (đủ điều kiện) hoặc nhập alt tay
4.1.2checkNameRoleValue :651App AI / ThemesAI credit hoặc thêm aria-label đúng ngôn ngữ store
Minor & auto

Cách fix

WCAGFix (theme, +1/lỗi)
2.4.2<title>{{ page_title }} | {{ shop.name }}</title>
3.1.1<html lang="{{ request.locale.iso_code }}">
3.2.1Chuyển logic khỏi focus sang click/submit handler
3.2.2Thêm nút Submit/Go, bỏ auto-redirect khỏi onchange
4.1.3Thêm role="status"/"alert" + aria-live (credit nếu AI ON)

⚪ 1.4.11, 2.4.11, 2.5.8, 3.3.2 auto-solved; 4.1.1 checker disabled — bỏ khỏi checklist.

⚠️ Alt AI = runtime/Firestore, KHÔNG ghi product data (app không có scope write_products). Muốn alt trong data thật → nhập tay Admin.

Tham khảo

Access · Mark-as-Solved · DevZone

  • 1Access: xin đúng scope (Pages/Content/Themes, không "All"), duplicate theme trước khi sửa, xong nhắc khách revoke.
  • 2Mark-as-Solved: chỉ merchant tự tick (qua field merchantMarkAsSolved). TS/CS không tick hộ, không dùng để làm đẹp điểm.
  • 3DevZone khi app buggy: Reset background scan (POST /accessibility-scanner/reset-background-scan) khi scan kẹt; DOM Accessibility Scan để triage offline, không đụng store thật.
1 / 18
Accessibility Training · 2026
← → chuyển slide · F fullscreen