⌨️ Thế Giới Keycap Docs SEO

SEO_CONTENT.md — thegioikeycap.vn

Nội dung danh mục, quy tắc index, sitemap. Plugin SEO: Rank Math.


Sửa nội dung mô tả danh mục ở đâu

Sản phẩm → Danh mục → bấm vào danh mục → ô "Mô tả".

Có trình soạn thảo đầy đủ (in đậm, tiêu đề, bảng, ảnh). Nội dung hiện bên dưới lưới sản phẩm.

Trước 06/09/2026 nội dung nằm trong data/category-seo.json và phải sửa file. Đã chuyển sang ô Mô tả; file JSON vẫn còn nhưng là dead data — giữ làm bản lưu, không code nào đọc nữa.


⚠️ BẪY KSES — đọc trước khi đụng inc/category-content.php

Lõi WordPress lọc mô tả taxonomy bằng bộ thẻ cấp bình luận:

add_filter( 'pre_term_description', 'wp_filter_kses' );

Bộ thẻ đó không có h2, p, table, img, ul. Filter này luôn bật, kể cả với admin có quyền unfiltered_html, và kses_init_filters() không đụng tới nó.

Đo thật: chuỗi 115 ký tự có h2/p/table/img lưu xong còn 25 ký tự — không có thông báo lỗi nào.

Theme nới bộ thẻ lên cấp bài viết cho hai ngữ cảnh:

add_filter( 'wp_kses_allowed_html', function ( $tags, $context ) {
    if ( in_array( $context, [ 'pre_term_description', 'term_description' ], true ) ) {
        return wp_kses_allowed_html( 'post' );
    }
    return $tags;
}, 10, 2 );
  • pre_term_description — lúc lưu
  • term_description — lúc hiện trong admin

Gỡ đoạn này ra là lần lưu danh mục kế tiếp xoá sạch nội dung.


Vì sao mô tả nằm dưới lưới sản phẩm

WooCommerce mặc định in mô tả ở đầu trang danh mục. Theme gỡ woocommerce_taxonomy_archive_description và in lại ở cuối qua tgk_category_seo_box().

Lý do: nội dung danh mục ở đây dài 20.000+ ký tự. Để lên đầu thì khách phải cuộn qua cả bài mới nhìn thấy sản phẩm.


Quy tắc index: có nội dung thì index

Rank Math bật sẵn noindex_empty_taxonomies, nên danh mục chưa có sản phẩm bị noindex kể cả khi đã có nội dung đầy đủ.

Theme đảo lại quy tắc: có nội dung (≥ 300 ký tự chữ) thì index, không có thì thôi.

const TGK_INDEX_MIN_CHARS = 300;

Nhờ vậy đẩy được bài lên trước, cho Google index và tích luỹ thứ hạng, rồi mới nhập hàng sau.

⚠️ Ưu tiên cờ noindex tường minh trong Rank Math (Cập nhật 04/10/2026): Nếu termmeta rank_math_robots có chứa noindex (do admin đặt thủ công qua Rank Math term meta), theme sẽ tôn trọng và không ép index, đồng thời loại khỏi sitemap.

Áp dụng cho 4 danh mục hiện tại chưa có sản phẩm nào để bán: keycap-mca, keycap-pudding, keycap-sa, keycap-xuyen-led. Khi shop nhập hàng về, chỉ cần xóa termmeta noindex trong admin thì quy tắc tự động index khi ≥ 300 ký tự sẽ kích hoạt trở lại.

⚠️ KHÔNG tắt noindex_empty_taxonomies trong cài đặt Rank Math. Làm vậy là mở index cho mọi danh mục rỗng, gồm uncategorized và danh mục tạo lỡ tay.

Hook liên quan trong inc/category-content.php:

  • rank_math/frontend/robots — quyết định thẻ robots
  • rank_math/sitemap/entry — lọc lại entry trong sitemap

⚠️ Sitemap cần MỘT cài đặt nằm trong DB

Rank Math → Sitemap Settings → Product Categories → Include Empty Terms = On (đã bật 06/09/2026).

Cài đặt này nằm trong DB nên không có trong git — dựng lại site là phải bật tay.

Thiếu nó thì danh mục chưa có sản phẩm không vào sitemap dù thẻ robots đã là index. Provider của Rank Math lấy hide_empty từ chính cài đặt đó (class-taxonomy.php dòng 242).

⚠️ Filter exclude_empty_terms KHÔNG thay được chỗ này — nó chỉ ảnh hưởng khâu đếm trang. Đã thử sai hai lần.

Theme lọc lại qua rank_math/sitemap/entry để danh mục rỗng nội dung vẫn bị loại khỏi sitemap. Kết quả: vào sitemap ⇔ có nội dung thật.

Đổi mô tả danh mục xong nhớ xoá cache sitemap của Rank Math, nếu không sitemap còn giữ bản cũ.


Trạng thái nội dung danh mục

Đã có nội dung (10/11): keycap, keycap-mda, keycap-moa, keycap-oem, keycap-xda, keycap-sa, keycap-mca, keycap-pudding, keycap-xuyen-led, ban-phim-co.

Cố ý để trống: uncategorized.


Meta title / description

Nguồn: data/category-meta.json, đọc bằng tgk_category_meta( $slug ). Khác với mô tả (nội dung dài trong admin) — đây chỉ là thẻ meta.

Cập nhật meta /keycap-xda/ (04/10/2026)

  • Lý do đổi: Sau khi 301 bài viết profile-keycap-xda-la-gi về danh mục /keycap-xda/ (hiệu lực từ 26/07/2026), dữ liệu GSC theo dimension page ghi nhận vị trí trung bình cải thiện từ 8.4 → 4.2, nhưng CTR bị giảm một nửa từ 4.7% → 2.4% (clicks giảm từ 13 xuống 7). Nguyên nhân do snippet cũ chỉ thuần bán hàng, không trả lời search intent định nghĩa ("XDA profile là gì"). Meta mới bổ sung giải thích ngắn ("phím phẳng đồng đều 9mm gõ êm, dễ làm quen") kết hợp intent thương mại để hồi phục CTR.
  • Mốc xem lại: 04/11/2026 chạy python3 scripts/analyze_301_pairs.py (đối soát số liệu theo dimension page) để đánh giá lại CTR và clicks của /keycap-xda/.

Cập nhật meta /test-ban-phim/ và liên kết điều hướng (04/10/2026)

  • Lý do: Trang /test-ban-phim/ có 2.295 hiển thị nhưng CTR chỉ 0,2%, query chính "test phím" (795 hiển thị, vị trí 10). Cập nhật title chứa đúng cụm "Test phím" + "kiểm tra bàn phím" (không hứa chính xác 100%) và thêm khối CTA dẫn sang /keycap/ dưới công cụ. Đồng thời thêm khối callout điều hướng trong bài /cac-loai-keycap/ (query "các mẫu keycap đẹp", vị trí 9) dẫn sang /keycap/.
  • Mốc xem lại: 04/11/2026 kiểm tra CTR và thứ hạng của /test-ban-phim/ và /cac-loai-keycap/ trên Google Search Console.

Khớp Profile thực tế và bẫy 1688 (04/10/2026)

  • Sau khi shop kiểm hàng thực tế trong kho: 2 sản phẩm Keycap Dark Fragrance Original (#1483) và Keycap Lake Light Mountain Color Original (#1484) là khuôn OEM, không phải MDA. Cả 2 đã được cập nhật mô tả và chuyển từ danh mục keycap-mda sang keycap-oem.
  • Bài học: Xưởng 1688 ghi 原厂高度 (nguyên xưởng) nhưng hàng thực tế nhập về là OEM — luôn đối soát với shop bằng hàng thực tế, không dùng nhãn 1688 để tự suy đoán.

Redirect 301 bài viết cũ

tgk_blog_to_category() trong inc/seo.php giữ bảng ánh xạ bài viết cũ → danh mục. Chỉ gồm bài mà nội dung đúng chủ đề của danh mục đích — redirect bài lệch chủ đề là tự hại mình.

tgk_redirected_post_ids() trả về ID các bài đã 301 để loại khỏi sitemap và khỏi danh sách bài viết.


tgk_setup_permalinks() giữ /{slug}/ cho product, product_cat và post.

Đây là cấu trúc của bản Astro cũ. Giữ nguyên để không vỡ SEO và backlink đã có.

Các URL trang phải giữ đúng: /san-pham/ /gio-hang/ /thanh-toan/ /tai-khoan/ /tai-khoan/don-hang/ /tin-tuc/ /test-ban-phim/


OG tag sản phẩm

inc/seo.php chỉ thêm 2 thẻ: product:retailer_item_id và product:condition.

⚠️ Rank Math đã tự xuất product:price:amount, product:price:currency, product:availability. Thêm nữa là trùng thẻ — đã sửa một lần vì chuyện này.


Schema JSON-LD cấu hình & tối ưu (04/10/2026)

  • Organization / ElectronicsStore:
  • telephone và sameAs (Facebook, Zalo) được bổ sung qua filter rank_math/json_ld trong inc/seo.php lấy trực tiếp từ tgk_site().
  • address dạng PostalAddress (streetAddress: "Số 1, Đường số 6", addressLocality: "Phường Hiệp Bình", addressRegion: "TP. Hồ Chí Minh", addressCountry: "VN") được cấu hình qua cài đặt Rank Math options local_address, tránh in trùng lặp.
  • Product Brand: Chỉ gán brand: {"@type": "Brand", "name": "LEOBOG"} cho các sản phẩm có thương hiệu rõ ràng (LEOBOG). Các bộ keycap không có thương hiệu thì không gán brand vì shop không phải nhà sản xuất.
  • Schema /test-ban-phim/: Tắt schema Article mặc định bằng rank_math_rich_snippet = 'off' trên trang 1584, chỉ giữ lại BreadcrumbList.

Công cụ kéo & phân tích dữ liệu Google Search Console (scripts/)

Các script hỗ trợ audit và giám sát dữ liệu tìm kiếm thực tế:

  • scripts/gsc_pull.py:
  • Kéo dữ liệu Search Console API 16 tháng qua Service Account (định danh GOOGLE_SHEETS_SA_KEY_BASE64 trong .secrets.env).
  • Lấy dữ liệu 2 tầng: [page, query, date] (phân tích intent) và [page, date] (lấy đúng tổng clicks/impressions trang bao gồm cả query ẩn danh).
  • Tự động gọi URL Inspection API và lấy sitemaps list.
  • Dữ liệu thô lưu tại scripts/data_gsc/ (đã khai báo trong .gitignore, không commit lên git).
  • scripts/analyze_301_pairs.py:
  • Đối chiếu hiệu năng trước/sau lệnh 301 (28 ngày pre vs post) theo đúng chuẩn [page, date].
  • Phân tích chi tiết nhóm query Informational vs Commercial và mức biến động thứ hạng.