<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mạnh Digital</title>
    <description>The latest articles on DEV Community by Mạnh Digital (@manhdigital68).</description>
    <link>https://dev.to/manhdigital68</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4194714%2F69f7eb2b-151d-4c15-a2bc-4aaaa51d6318.png</url>
      <title>DEV Community: Mạnh Digital</title>
      <link>https://dev.to/manhdigital68</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manhdigital68"/>
    <language>en</language>
    <item>
      <title>SEO AI khác SEO truyền thống ở đâu: nhìn từ phía người viết HTML</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Mon, 02 Nov 2026 02:40:13 +0000</pubDate>
      <link>https://dev.to/manhdigital68/seo-ai-khac-seo-truyen-thong-o-dau-nhin-tu-phia-nguoi-viet-html-4f60</link>
      <guid>https://dev.to/manhdigital68/seo-ai-khac-seo-truyen-thong-o-dau-nhin-tu-phia-nguoi-viet-html-4f60</guid>
      <description>&lt;p&gt;Dạo này khách hay hỏi team mình một câu: "Làm SEO AI thì dev phải sửa gì?". Câu hỏi nghe to, nhưng khi ngồi soát code thì phần việc của dev nhỏ hơn nhiều người nghĩ, và gần như toàn là những thứ SEO kỹ thuật vẫn nói từ lâu.&lt;/p&gt;

&lt;p&gt;Trước hết cần tách hai nghĩa của chữ "SEO AI". Nghĩa thứ nhất là dùng AI để làm SEO nhanh hơn, ví dụ nhờ ChatGPT gom từ khóa hay viết nháp. Nghĩa thứ hai là làm cho website được các công cụ tìm kiếm có AI như Google AI Overviews, ChatGPT, Gemini, Perplexity đọc được, hiểu đúng và nhắc tên khi người dùng hỏi. Bài này chỉ nói nghĩa thứ hai, và chỉ nói phần chạm tới code.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Nội dung chính phải có sẵn trong HTML ban đầu
&lt;/h2&gt;

&lt;p&gt;Đây là chỗ mình gặp lỗi nhiều nhất ở các site React hoặc framework tương tự. Mở trình duyệt thì thấy đủ, nhưng HTML server trả về chỉ có thế này:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/assets/app.3f9a.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Một con bot không chạy JavaScript sẽ chỉ đọc được cái khung rỗng đó. Thứ nên có là:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Dịch vụ sửa máy lạnh tại quận 7&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Giá kiểm tra từ 150.000đ, có mặt trong 2 giờ, bảo hành 3 tháng.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    ...
  &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/assets/app.3f9a.js"&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Ví dụ trên là doanh nghiệp giả định, chỉ để minh họa cấu trúc.)&lt;/p&gt;

&lt;p&gt;Cách kiểm nhanh nhất: &lt;code&gt;curl -s https://example.com/trang-dich-vu | grep -i "câu quan trọng nhất của trang"&lt;/code&gt;. Không ra kết quả thì cần SSR, pre-render hoặc static generation cho trang đó.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Câu trả lời đặt ngay đầu đoạn, không giấu sau ba lớp mở bài
&lt;/h2&gt;

&lt;p&gt;SEO truyền thống đã khuyên viết rõ ràng, nhưng với công cụ AI thì chuyện này càng đáng làm: người dùng hỏi một câu cụ thể, câu trả lời của bạn nên nằm ngay sau heading, có con số.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"gia"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Sửa máy lạnh giá bao nhiêu?&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Phí kiểm tra 150.000đ, được trừ vào tiền sửa nếu khách đồng ý sửa.
     Thay gas từ 350.000đ tùy loại máy.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Không cần markup đặc biệt nào. Một &lt;code&gt;h2&lt;/code&gt; là câu hỏi thật, một &lt;code&gt;p&lt;/code&gt; là câu trả lời thật, thế là đủ để cả người lẫn máy đọc.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Không cần file "dành riêng cho AI" để lên AI Overviews
&lt;/h2&gt;

&lt;p&gt;Google nói rõ AI Overviews và AI Mode lấy nguồn từ chỉ mục Google Search: trang chỉ cần được index và đủ điều kiện hiện đoạn trích. Không cần file hay markup gì riêng. &lt;code&gt;llms.txt&lt;/code&gt; hiện vẫn là một đề xuất; thêm vào không tốn bao nhiêu, nhưng đừng xem nó là việc chính.&lt;/p&gt;

&lt;p&gt;Với ChatGPT thì khác một chút: OpenAI tách bot tìm kiếm (OAI-SearchBot) khỏi bot huấn luyện (GPTBot), bật tắt riêng trong robots.txt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User-agent: GPTBot
Disallow: /

User-agent: OAI-SearchBot
Allow: /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cấu hình trên nghĩa là không cho dùng nội dung để huấn luyện, nhưng vẫn cho ChatGPT tìm thấy site. Mình đã viết riêng một bài về &lt;a href="https://dev.to/manhdigital68/kiem-tra-ai-crawler-co-doc-duoc-site-khong-robotstxt-html-ban-dau-va-log-server-3cc6"&gt;cách kiểm tra AI crawler có đọc được site không&lt;/a&gt;, có lệnh lọc log server theo từng bot.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Thông tin thực thể phải giống nhau ở mọi nơi
&lt;/h2&gt;

&lt;p&gt;AI hay nhầm nhất khi tên công ty, địa chỉ, dịch vụ, khoảng giá mỗi nơi ghi một kiểu. Phần dev làm được là đưa đúng các thông tin đó vào footer, trang Giới thiệu và JSON-LD &lt;code&gt;Organization&lt;/code&gt;, kèm &lt;code&gt;sameAs&lt;/code&gt; trỏ tới các hồ sơ chính thức. Chi tiết khai báo có trong bài &lt;a href="https://dev.to/manhdigital68/khai-bao-organization-sameas-bang-json-ld-de-ai-khong-nham-thuong-hieu-cua-ban-4koa"&gt;khai báo Organization và sameAs bằng JSON-LD&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Đo bằng thứ đang có, không cần tool lạ
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Lượt nhấp từ AI Overviews được tính chung trong báo cáo Hiệu suất của Search Console.&lt;/li&gt;
&lt;li&gt;Trong GA4, lọc nguồn giới thiệu &lt;code&gt;chatgpt.com&lt;/code&gt; và &lt;code&gt;perplexity.ai&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Ghi 15 đến 20 câu khách hay hỏi, mỗi tháng hỏi lại các công cụ AI một lần và chép kết quả vào bảng. Một lần được nhắc tên chưa nói lên gì; phải nhìn qua nhiều kỳ.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tóm lại cho dev
&lt;/h2&gt;

&lt;p&gt;Phần lớn "SEO AI" ở tầng code chính là SEO kỹ thuật làm cho đúng: HTML có nội dung, robots.txt cấu hình có chủ ý, thông tin thực thể nhất quán. Nền mà hỏng thì thêm việc ở lớp trên cũng không cứu được.&lt;/p&gt;

&lt;p&gt;Nếu bạn cần phần giải thích cho người không làm kỹ thuật (sếp, khách hàng), bài &lt;a href="https://manhdigital.com/blog/seo-ai-la-gi" rel="noopener noreferrer"&gt;SEO AI là gì mà dạo này ai cũng nói&lt;/a&gt; của Mạnh Digital viết khá dễ hiểu, có cả hai lời hứa nên hỏi lại trước khi trả tiền cho dịch vụ.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>ai</category>
      <category>webdev</category>
      <category>html</category>
    </item>
    <item>
      <title>Kiểm tra AI crawler có đọc được site không: robots.txt, HTML ban đầu và log server</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Thu, 29 Oct 2026 07:43:23 +0000</pubDate>
      <link>https://dev.to/manhdigital68/kiem-tra-ai-crawler-co-doc-duoc-site-khong-robotstxt-html-ban-dau-va-log-server-3cc6</link>
      <guid>https://dev.to/manhdigital68/kiem-tra-ai-crawler-co-doc-duoc-site-khong-robotstxt-html-ban-dau-va-log-server-3cc6</guid>
      <description>&lt;p&gt;Tuần trước một người quen nhờ mình xem vì sao ChatGPT trả lời về công ty anh ấy toàn thông tin cũ. Nội dung không sai, schema cũng có. Kiểm tra một lúc mới ra nguyên nhân rất "dev": robots.txt đang chặn một bot tìm kiếm của AI, còn trang dịch vụ thì phần mô tả chỉ hiện ra sau khi JavaScript chạy xong.&lt;/p&gt;

&lt;p&gt;Bài này ghi lại cách mình kiểm tra theo ba lớp: robots.txt, HTML ban đầu và log server. Toàn bộ chỉ cần terminal, &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt; và quyền đọc access log. Mình không bàn chuyện nội dung hay thực thể ở đây, chỉ xem bot có vào được và đọc được hay không.&lt;/p&gt;

&lt;h2&gt;
  
  
  Các user-agent nên biết
&lt;/h2&gt;

&lt;p&gt;Không có danh sách nào đầy đủ mãi, nhưng đây là những cái mình hay gặp nhất:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPTBot&lt;/strong&gt; (OpenAI): thu thập nội dung có thể dùng để huấn luyện mô hình. Chặn GPTBot nghĩa là bạn không muốn nội dung bị dùng cho việc đó.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAI-SearchBot&lt;/strong&gt; (OpenAI): dùng cho tính năng tìm kiếm của ChatGPT. Theo tài liệu của OpenAI, site chặn bot này sẽ không xuất hiện trong câu trả lời tìm kiếm của ChatGPT (vẫn có thể hiện dạng link điều hướng).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ChatGPT-User&lt;/strong&gt; (OpenAI): truy cập khi người dùng yêu cầu ChatGPT mở một trang. OpenAI ghi rõ đây là hành động do người dùng khởi tạo nên robots.txt có thể không áp dụng.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ClaudeBot&lt;/strong&gt; (Anthropic) và &lt;strong&gt;PerplexityBot&lt;/strong&gt; (Perplexity): crawler của hai nền tảng này.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google-Extended&lt;/strong&gt;: chỉ là một token trong robots.txt, không có user-agent riêng nên bạn sẽ không thấy nó trong log. Google dùng nó để bạn chọn có cho nội dung phục vụ Gemini hay không; nó không ảnh hưởng tới việc trang có lên Google Search. AI Overviews vẫn đi theo Googlebot và index thông thường.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Điểm quan trọng: ba bot của OpenAI là ba thiết lập độc lập. Bạn hoàn toàn có thể mở OAI-SearchBot để được tìm thấy trong ChatGPT search mà vẫn chặn GPTBot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lớp 1: đọc robots.txt cho đúng
&lt;/h2&gt;

&lt;p&gt;Đầu tiên lấy file về:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://example.com/robots.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chỗ nhiều người đọc nhầm: một crawler chỉ theo &lt;strong&gt;nhóm user-agent khớp cụ thể nhất&lt;/strong&gt; với nó. Nếu file có nhóm &lt;code&gt;User-agent: GPTBot&lt;/code&gt; thì GPTBot bỏ qua hoàn toàn nhóm &lt;code&gt;User-agent: *&lt;/code&gt;, kể cả các dòng &lt;code&gt;Disallow&lt;/code&gt; bạn tưởng là áp dụng cho mọi bot. Ví dụ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User-agent: *
Disallow: /admin/

User-agent: GPTBot
Disallow: /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ở đây GPTBot bị chặn toàn site, còn OAI-SearchBot, ClaudeBot, PerplexityBot rơi vào nhóm &lt;code&gt;*&lt;/code&gt; nên chỉ bị chặn &lt;code&gt;/admin/&lt;/code&gt;. Nếu bạn muốn cho bot tìm kiếm vào nhưng chặn bot huấn luyện, viết rõ từng nhóm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User-agent: OAI-SearchBot
Allow: /

User-agent: GPTBot
Disallow: /

User-agent: Google-Extended
Disallow: /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mình hay lọc nhanh các dòng liên quan bằng:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://example.com/robots.txt &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-inE&lt;/span&gt; &lt;span class="nt"&gt;-A3&lt;/span&gt; &lt;span class="s1"&gt;'user-agent: *(\*|gptbot|oai-searchbot|chatgpt-user|claudebot|perplexitybot|google-extended)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hai lỗi mình gặp nhiều nhất: plugin bảo mật hoặc CDN tự thêm nhóm chặn "AI bots" mà chủ site không biết, và robots.txt bị trả về 403 hoặc trang HTML lỗi thay vì file text. Kiểm tra luôn status và content-type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://example.com/robots.txt | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s1"&gt;'^(HTTP|content-type)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenAI cũng lưu ý thay đổi robots.txt có thể mất khoảng 24 giờ để hệ thống tìm kiếm của họ cập nhật, nên đừng sửa xong rồi thử ngay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lớp 2: gọi trang bằng user-agent của bot và xem HTML ban đầu
&lt;/h2&gt;

&lt;p&gt;robots.txt cho phép không có nghĩa là server cho phép. WAF, Cloudflare hay rule chống bot có thể trả 403, 429 hoặc trang challenge cho đúng mấy user-agent này. Mình giả lập bằng &lt;code&gt;curl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/dich-vu/abc"&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;UA &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ChatGPT-User/1.0; +https://openai.com/bot"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"OAI-SearchBot/1.4"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"ClaudeBot/1.0"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"PerplexityBot/1.0"&lt;/span&gt;
&lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%-20s '&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$UA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oE&lt;/span&gt; &lt;span class="s1"&gt;'(GPTBot|ChatGPT-User|OAI-SearchBot|ClaudeBot|PerplexityBot)'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$UA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s1"&gt;'%{http_code} %{size_download} bytes\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chuỗi user-agent đầy đủ có số phiên bản thay đổi theo thời gian; với việc kiểm tra rule chặn theo tên thì chỉ cần chứa đúng tên bot là đủ. Kết quả cần nhìn: mọi dòng nên là &lt;code&gt;200&lt;/code&gt; và kích thước gần bằng nhau. Một dòng &lt;code&gt;403&lt;/code&gt;, hoặc &lt;code&gt;200&lt;/code&gt; nhưng chỉ vài KB trong khi trình duyệt nhận cả trăm KB, thường là trang challenge.&lt;/p&gt;

&lt;p&gt;Lưu ý: cách này chỉ kiểm tra được rule chặn theo user-agent. Nếu firewall chặn theo IP hoặc ASN thì &lt;code&gt;curl&lt;/code&gt; từ máy bạn vẫn qua, còn bot thật thì không. Vì vậy cần lớp 3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nội dung có nằm trong HTML ban đầu không
&lt;/h3&gt;

&lt;p&gt;Nhiều bot AI đọc HTML trả về chứ không chạy JavaScript như trình duyệt. Nếu site là SPA render phía client, bot có thể chỉ thấy một &lt;code&gt;&amp;lt;div id="root"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; trống.&lt;/p&gt;

&lt;p&gt;Cách kiểm tra đơn giản: chọn một câu quan trọng (tên dịch vụ, giá, địa chỉ) và grep trong HTML thô:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"GPTBot/1.4"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"Dịch vụ thiết kế website"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ra &lt;code&gt;0&lt;/code&gt; thì có hai khả năng: nội dung do JS tạo ra, hoặc chuỗi bị encode thành HTML entity. Để chắc, mình bỏ thẻ và xem phần text thô:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"GPTBot/1.4"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import sys,re,html; t=sys.stdin.read(); t=re.sub(r'&amp;lt;(script|style)[^&amp;gt;]*&amp;gt;.*?&amp;lt;/&lt;/span&gt;&lt;span class="se"&gt;\1&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;','',t,flags=re.S); t=html.unescape(re.sub(r'&amp;lt;[^&amp;gt;]+&amp;gt;','&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;',t)); print('&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;'.join(l.strip() for l in t.splitlines() if l.strip()))"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nếu 50 dòng đầu chỉ có menu, footer và "Loading...", đó là dấu hiệu nội dung chính không nằm trong HTML ban đầu. Hướng sửa thường là SSR, SSG hoặc prerender cho các trang quan trọng; tùy framework mà cách làm khác nhau.&lt;/p&gt;

&lt;p&gt;Cũng nên kiểm tra thêm &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;, meta description và thẻ &lt;code&gt;&amp;lt;meta name="robots"&amp;gt;&lt;/code&gt; trong HTML thô, vì có site gắn &lt;code&gt;noindex&lt;/code&gt; bằng JS rồi quên gỡ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oiE&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;(title|meta name="(description|robots)")[^&amp;gt;]*&amp;gt;[^&amp;lt;]*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lớp 3: đọc access log
&lt;/h2&gt;

&lt;p&gt;Đây là nơi trả lời câu hỏi "bot có thực sự ghé không". Với log nginx hoặc Apache dạng combined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Đếm lượt truy cập theo từng bot (gồm cả log đã nén)&lt;/span&gt;
zgrep &lt;span class="nt"&gt;-hoiE&lt;/span&gt; &lt;span class="s1"&gt;'GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|PerplexityBot'&lt;/span&gt; /var/log/nginx/access.log&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Xem bot gặp status nào, ở URL nào&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s1"&gt;'GPTBot|OAI-SearchBot|ClaudeBot|PerplexityBot'&lt;/span&gt; /var/log/nginx/access.log &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $9, $7}'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nếu thấy nhiều &lt;code&gt;403&lt;/code&gt; hoặc &lt;code&gt;429&lt;/code&gt;, quay lại xem rule WAF hoặc rate limit. Nếu hoàn toàn không có dòng nào sau vài tuần, có thể bot chưa biết tới site, hoặc bị chặn từ tầng CDN trước khi request tới server; khi đó cần xem log hoặc dashboard của CDN.&lt;/p&gt;

&lt;p&gt;User-agent thì ai cũng giả được. OpenAI công bố dải IP cho từng bot ở các file JSON như &lt;code&gt;https://openai.com/gptbot.json&lt;/code&gt;, &lt;code&gt;searchbot.json&lt;/code&gt;, &lt;code&gt;chatgpt-user.json&lt;/code&gt;. Mình kiểm tra một IP trong log như sau:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"20.171.206.10"&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://openai.com/gptbot.json &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.prefixes[] | .ipv4Prefix // .ipv6Prefix'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import sys,ipaddress; ip=ipaddress.ip_address('&lt;/span&gt;&lt;span class="nv"&gt;$IP&lt;/span&gt;&lt;span class="s2"&gt;'); print(any(ip in ipaddress.ip_network(l.strip()) for l in sys.stdin if l.strip()))"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ra &lt;code&gt;True&lt;/code&gt; thì đúng là bot của OpenAI. Với các bot khác, xem trang tài liệu crawler của từng bên để lấy cách xác minh tương ứng.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist ngắn
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;robots.txt trả &lt;code&gt;200&lt;/code&gt;, &lt;code&gt;text/plain&lt;/code&gt;, không có nhóm chặn bot mà bạn không chủ động thêm.&lt;/li&gt;
&lt;li&gt;Mỗi bot bạn muốn cho vào được xử lý đúng nhóm user-agent của nó, không trông vào nhóm &lt;code&gt;*&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;curl&lt;/code&gt; với từng user-agent đều ra &lt;code&gt;200&lt;/code&gt; và kích thước tương đương trình duyệt.&lt;/li&gt;
&lt;li&gt;Câu quan trọng nhất của trang có trong HTML thô, không cần JS.&lt;/li&gt;
&lt;li&gt;Không có &lt;code&gt;noindex&lt;/code&gt; ngoài ý muốn trong HTML ban đầu.&lt;/li&gt;
&lt;li&gt;Log có lượt truy cập từ bot, status chủ yếu là &lt;code&gt;200&lt;/code&gt;, IP khớp dải được công bố.&lt;/li&gt;
&lt;li&gt;Trang đã được Google index, vì AI Overviews chỉ lấy nguồn từ trang đủ điều kiện hiển thị trên Google Search.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ba lớp này chỉ trả lời câu hỏi bot có đọc được site hay không. Đọc được rồi mà AI vẫn tả sai công ty thì vấn đề nằm ở nội dung và nguồn bên ngoài; phần đó mình đã viết riêng trong &lt;a href="https://manhdigital68.hashnode.dev/checklist-30-ph-t-v-sao-chatgpt-t-sai-c-ng-ty-c-a-b-n" rel="noopener noreferrer"&gt;checklist 30 phút tìm lý do ChatGPT mô tả sai doanh nghiệp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nếu bạn không có quyền đọc log hay không muốn tự mò rule CDN, Mạnh Digital có &lt;a href="https://manhdigital.com/dich-vu/seo-ai" rel="noopener noreferrer"&gt;dịch vụ tối ưu cho AI search&lt;/a&gt;, trong đó phần kỹ thuật gồm đưa nội dung quan trọng vào HTML ban đầu và cấu hình robots.txt cho các bot AI. Còn nếu tự làm, chạy hết checklist trên một lần là đã loại được phần lớn lỗi mình hay gặp.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>ai</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>10 dòng rà lại trước khi bấm Đăng một bài SEO (kèm 3 lệnh curl)</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Wed, 28 Oct 2026 02:33:54 +0000</pubDate>
      <link>https://dev.to/manhdigital68/10-dong-ra-lai-truoc-khi-bam-dang-mot-bai-seo-kem-3-lenh-curl-5cj9</link>
      <guid>https://dev.to/manhdigital68/10-dong-ra-lai-truoc-khi-bam-dang-mot-bai-seo-kem-3-lenh-curl-5cj9</guid>
      <description>&lt;p&gt;Viết xong một bài SEO, phần dễ bỏ sót nhất không nằm ở nội dung mà ở mấy phút cuối trước khi bấm Đăng. Mình gom lại thành 10 dòng, mỗi dòng là một câu hỏi trả lời được bằng "có" hoặc "không". Dòng nào ra "không" thì sửa xong mới đăng.&lt;/p&gt;

&lt;p&gt;Danh sách này là phần rà cuối, không thay cho brief hay dàn ý. Nếu bạn cần cả khung từ đầu (brief, heading, ví dụ đã điền), mình đang dùng &lt;a href="https://manhdigital.com/blog/mau-bai-viet-chuan-seo" rel="noopener noreferrer"&gt;template bài viết SEO&lt;/a&gt; của Mạnh Digital rồi mới chạy 10 dòng này ở cuối.&lt;/p&gt;

&lt;h2&gt;
  
  
  10 dòng rà trước khi đăng
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ] 1. Intent: nói được nhiệm vụ của URL này trong một câu
[ ] 2. Trả lời trước: 100–150 từ đầu cho người đọc kết luận dùng được
[ ] 3. Title + H1: đúng chủ đề, không hứa nhiều hơn nội dung có
[ ] 4. Meta description: có lợi ích và điểm khác biệt, không lặp title
[ ] 5. Heading: viết theo câu hỏi, không nhồi keyword vào mọi H2
[ ] 6. Nguồn: claim cụ thể (số liệu, chính sách Google) có link tài liệu gốc
[ ] 7. Internal link: có pillar, bài liên quan, anchor mô tả đúng trang đích
[ ] 8. Ảnh + mobile: ảnh có alt, bảng cuộn ngang được, chữ quan trọng không chỉ nằm trong ảnh
[ ] 9. Technical: trả về 200, canonical trỏ chính nó, indexable, nội dung chính có trong HTML ban đầu
[ ] 10. Đo lường: đã ghi ngày check index và query cần theo dõi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Có thể dán khối này vào phần mô tả task, checklist của pull request nếu blog chạy bằng Git, hoặc một ô ghi chú trong CMS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ba dòng kiểm bằng terminal cho nhanh
&lt;/h2&gt;

&lt;p&gt;Dòng 9 là dòng hay bị bỏ qua nhất, vì nhìn trên trình duyệt thì bài vẫn hiện bình thường. Ba lệnh dưới đây kiểm phần lớn của nó trong vài giây (thay &lt;code&gt;URL&lt;/code&gt; bằng link bài):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1) Mã phản hồi cuối cùng, phải là 200&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; URL

&lt;span class="c"&gt;# 2) Canonical và meta robots có trong HTML trả về không&lt;/span&gt;
curl &lt;span class="nt"&gt;-sL&lt;/span&gt; URL | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oiE&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;link[^&amp;gt;]+rel="canonical"[^&amp;gt;]*&amp;gt;|&amp;lt;meta[^&amp;gt;]+name="robots"[^&amp;gt;]*&amp;gt;'&lt;/span&gt;

&lt;span class="c"&gt;# 3) Một câu trong đoạn mở bài có nằm sẵn trong HTML ban đầu không&lt;/span&gt;
curl &lt;span class="nt"&gt;-sL&lt;/span&gt; URL | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"một cụm chữ trong đoạn mở bài"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lệnh 3 ra &lt;code&gt;0&lt;/code&gt; mà trên trình duyệt vẫn thấy chữ thì nhiều khả năng nội dung được JavaScript dựng sau khi tải trang. Không phải lúc nào cũng hỏng, nhưng đáng hỏi lại người làm web trước khi đăng hàng loạt bài cùng kiểu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vì sao là "có/không" chứ không chấm điểm
&lt;/h2&gt;

&lt;p&gt;Chấm mỗi mục trên thang 1–5 rất dễ ra kiểu bài nào cũng 3–4 điểm, nhìn thì ổn mà không biết phải sửa gì. Có/không thì mỗi lần ra "không" là có một việc cụ thể phải làm, ví dụ "thêm link nguồn cho con số ở đoạn 2", nên dễ chốt hơn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Những chỗ hay ra "không"
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dòng 2: mở bài kể bối cảnh ba đoạn rồi mới vào câu trả lời.&lt;/li&gt;
&lt;li&gt;Dòng 6: dẫn một con số "theo nghiên cứu" nhưng không có link.&lt;/li&gt;
&lt;li&gt;Dòng 7: bài mới đăng không có link nào trỏ vào, kể cả từ bài cùng cụm.&lt;/li&gt;
&lt;li&gt;Dòng 10: đăng xong là quên, không ai nhớ ngày nào cần xem lại index.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Đọc thêm
&lt;/h2&gt;

&lt;p&gt;Nếu muốn tự động hoá phần kiểm tra template thay vì tick tay, mình có viết cách &lt;a href="https://dev.to/manhdigital68/bien-template-bai-viet-chuan-seo-thanh-yaml-script-python-kiem-tra-tu-dong-858"&gt;biến template bài viết chuẩn SEO thành YAML và script Python kiểm tra&lt;/a&gt;. Còn bản dàn ý markdown để copy dùng ngay thì ở &lt;a href="https://hackmd.io/@manhdigital68/B1eGPvw3zg" rel="noopener noreferrer"&gt;note HackMD outline bài SEO&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Bạn có dòng nào hay rà mà danh sách này chưa có không? Mình đang muốn thêm một dòng cho phần schema mà chưa chốt được cách hỏi ngắn gọn.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>writing</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Đọc Search Console theo từng tháng: 7 tín hiệu SEO sớm trước khi có traffic</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Mon, 26 Oct 2026 17:05:11 +0000</pubDate>
      <link>https://dev.to/manhdigital68/doc-search-console-theo-tung-thang-7-tin-hieu-seo-som-truoc-khi-co-traffic-159e</link>
      <guid>https://dev.to/manhdigital68/doc-search-console-theo-tung-thang-7-tin-hieu-seo-som-truoc-khi-co-traffic-159e</guid>
      <description>&lt;p&gt;Giả sử bạn mở Search Console vào tháng thứ hai sau khi bắt đầu làm SEO. Click: 0. Bạn khép máy lại và nghĩ: chắc SEO không chạy rồi.&lt;/p&gt;

&lt;p&gt;(Đây là tình huống minh họa, không phải một dự án cụ thể.)&lt;/p&gt;

&lt;p&gt;Vấn đề là click thường đến muộn. Trước khi có click, có những tín hiệu nhỏ hơn đã xuất hiện, chỉ là ít ai mở đúng báo cáo để xem. Dưới đây là 7 tín hiệu mình hay kiểm tra theo thứ tự.&lt;/p&gt;

&lt;h2&gt;
  
  
  7 tín hiệu và mốc tham khảo
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Tín hiệu&lt;/th&gt;
&lt;th&gt;Xem ở đâu&lt;/th&gt;
&lt;th&gt;Mốc tham khảo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Số trang được lập chỉ mục tăng&lt;/td&gt;
&lt;td&gt;GSC &amp;gt; Pages&lt;/td&gt;
&lt;td&gt;Tháng 1-2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Impressions tăng dù click còn thấp&lt;/td&gt;
&lt;td&gt;GSC &amp;gt; Performance&lt;/td&gt;
&lt;td&gt;Tháng 2-3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Từ khóa dài có click đầu tiên&lt;/td&gt;
&lt;td&gt;GSC &amp;gt; Queries&lt;/td&gt;
&lt;td&gt;Tháng 3-4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Vị trí trung bình cải thiện&lt;/td&gt;
&lt;td&gt;GSC &amp;gt; Performance&lt;/td&gt;
&lt;td&gt;Tháng 3-5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;CTR tăng sau khi sửa title và meta&lt;/td&gt;
&lt;td&gt;GSC &amp;gt; Performance&lt;/td&gt;
&lt;td&gt;Tháng 4-6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Organic traffic tăng ổn định&lt;/td&gt;
&lt;td&gt;GA4 &amp;gt; Acquisition&lt;/td&gt;
&lt;td&gt;Tháng 5-8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Lead hoặc đơn từ organic&lt;/td&gt;
&lt;td&gt;GA4 &amp;gt; Conversions&lt;/td&gt;
&lt;td&gt;Tháng 6-9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Các mốc này chỉ để định hướng, không phải cam kết. Site mới, ngành cạnh tranh cao hoặc nội dung mỏng đều có thể đi chậm hơn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cách đọc từng tín hiệu
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Index tăng.&lt;/strong&gt; Nếu trang chưa được index thì mọi thứ phía sau đều chưa bắt đầu. Kiểm tra mục Pages, xem lý do trang bị loại, và gửi lại URL quan trọng qua URL Inspection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impressions tăng.&lt;/strong&gt; Google bắt đầu hiển thị trang của bạn cho một số truy vấn, dù bạn còn ở trang 3-4 nên chưa ai bấm. Đây là dấu hiệu sớm đáng chú ý nhất.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Từ khóa dài có click.&lt;/strong&gt; Cụm dài, ít cạnh tranh thường cho click đầu tiên. Hãy lọc Queries theo độ dài và theo trang, đừng chỉ nhìn tổng.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vị trí trung bình.&lt;/strong&gt; Con số này dao động nhiều. Nhìn xu hướng theo tuần thay vì theo ngày, và so cùng một nhóm trang.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CTR.&lt;/strong&gt; Nếu impressions cao mà CTR thấp, vấn đề nhiều khi nằm ở title và meta description. Sửa chúng rồi chờ vài tuần để đo lại.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traffic và lead.&lt;/strong&gt; Hai tín hiệu này đến cuối cùng, vì chúng phụ thuộc vào cả 5 tín hiệu trước.&lt;/p&gt;

&lt;h2&gt;
  
  
  Một thói quen nhỏ
&lt;/h2&gt;

&lt;p&gt;Cuối mỗi tháng, chụp lại 3 con số: số trang index, tổng impressions, số query có ít nhất 1 click. Ba con số này đủ để bạn biết mình đang đi tiếp hay đang đứng yên, kể cả khi doanh thu chưa nhúc nhích.&lt;/p&gt;

&lt;p&gt;Mình có gom timeline 12 tháng và các giai đoạn nền móng, tăng trưởng, bứt phá, duy trì trong bài &lt;a href="https://manhdigital.com/blog/seo-mat-bao-lau" rel="noopener noreferrer"&gt;SEO mất bao lâu? trên ManhDigital&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Bạn thường thấy tín hiệu nào xuất hiện đầu tiên trong site của mình?&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>analytics</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Hứa "TOP 1 sau 2 tuần": đọc hợp đồng SEO thế nào để không mất quyền website</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Mon, 26 Oct 2026 02:33:57 +0000</pubDate>
      <link>https://dev.to/manhdigital68/hua-top-1-sau-2-tuan-doc-hop-dong-seo-the-nao-de-khong-mat-quyen-website-b70</link>
      <guid>https://dev.to/manhdigital68/hua-top-1-sau-2-tuan-doc-hop-dong-seo-the-nao-de-khong-mat-quyen-website-b70</guid>
      <description>&lt;p&gt;Có một kiểu tin nhắn mà ai làm chủ website cũng từng nhận: "Bên em cam kết TOP 1 Google sau 2 tuần, không lên không lấy tiền." Nghe rất an tâm. Nhưng câu hứa đó gần như không nói gì về việc họ sẽ làm gì trên website của bạn, và đó mới là chỗ cần đọc kỹ.&lt;/p&gt;

&lt;p&gt;Bài này không nhằm kết luận ai lừa ai. Kết quả SEO chậm có thể do website yếu, đối thủ mạnh hoặc thời gian còn ngắn. Mục tiêu ở đây hẹp hơn: đọc một lời hứa và một bản hợp đồng SEO sao cho, dù dự án tốt hay xấu, bạn vẫn giữ được tài khoản, dữ liệu và quyền quyết định.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Vì sao "TOP 1 trong X ngày" là câu cần hỏi lại
&lt;/h2&gt;

&lt;p&gt;Trong tài liệu "Do you need an SEO?", Google nói thẳng là không ai có thể đảm bảo vị trí số 1 trên Google. Thứ hạng phụ thuộc vào truy vấn, đối thủ, chất lượng trang và cả thay đổi thuật toán, không phải thứ một bên thứ ba bật tắt được.&lt;/p&gt;

&lt;p&gt;Vậy khi gặp câu hứa này, đừng tranh luận đúng sai. Hỏi lại ba câu:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TOP 1 cho từ khoá nào, đo bằng công cụ gì, ở thiết bị và khu vực nào?&lt;/li&gt;
&lt;li&gt;Trong 2 tuần đó, cụ thể các bạn sẽ thay đổi gì trên website?&lt;/li&gt;
&lt;li&gt;Nếu thứ hạng lên rồi rớt, điều khoản xử lý thế nào?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Câu trả lời mơ hồ ở câu thứ hai đáng lo hơn con số ở câu thứ nhất.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Năm điều khoản nên có trong hợp đồng SEO
&lt;/h2&gt;

&lt;p&gt;Đây là phần mình hay soi đầu tiên khi đọc giúp bạn bè một bản hợp đồng:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Điều khoản&lt;/th&gt;
&lt;th&gt;Nên ghi gì&lt;/th&gt;
&lt;th&gt;Dấu hiệu cần hỏi thêm&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Quyền sở hữu tài khoản&lt;/td&gt;
&lt;td&gt;Domain, hosting, CMS, Search Console, GA4 đứng tên doanh nghiệp&lt;/td&gt;
&lt;td&gt;Agency giữ tài khoản gốc, bạn chỉ được "xem báo cáo"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phạm vi công việc&lt;/td&gt;
&lt;td&gt;Số trang, số bài, loại hoạt động offpage, có số lượng&lt;/td&gt;
&lt;td&gt;Chỉ ghi "tối ưu tổng thể", "đẩy từ khoá"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phê duyệt thay đổi&lt;/td&gt;
&lt;td&gt;Đổi URL, redirect, xoá trang, cài mã phải được duyệt và ghi change log&lt;/td&gt;
&lt;td&gt;Không nhắc gì tới việc ai duyệt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Báo cáo&lt;/td&gt;
&lt;td&gt;Số liệu lấy từ GSC, GA4 mà bạn tự mở được&lt;/td&gt;
&lt;td&gt;Chỉ có ảnh chụp biểu đồ trong file PDF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bàn giao khi dừng&lt;/td&gt;
&lt;td&gt;Danh sách nội dung, thay đổi, backlink, tài khoản phải trả lại&lt;/td&gt;
&lt;td&gt;Không có điều khoản chấm dứt và bàn giao&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Một bản hợp đồng có đủ năm dòng này chưa chắc là dịch vụ tốt, nhưng nếu thiếu, bạn sẽ rất khó xử lý khi có chuyện.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Ba thói quen giúp tự bảo vệ ngay từ ngày đầu
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cấp quyền theo vai trò, không gửi mật khẩu.&lt;/strong&gt; Search Console, GA4, WordPress đều cho thêm người dùng với quyền riêng. Lúc mới đánh giá một đơn vị, Google cũng khuyên chỉ cấp quyền đọc Search Console.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Xuất dữ liệu gốc trước khi bắt đầu.&lt;/strong&gt; Click, impression, trang đích và chuyển đổi của 3 đến 6 tháng gần nhất. Đây là mốc để sau này đối chiếu, thay vì tin vào biểu đồ trong slide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ghi nhận mọi thay đổi lớn bằng văn bản.&lt;/strong&gt; Một email ngắn "đồng ý redirect /a sang /b" đủ để sau này biết ai đã làm gì và vì sao.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Nếu đã ký và bắt đầu thấy lạ
&lt;/h2&gt;

&lt;p&gt;Thứ hạng chưa tăng thì nên ngồi lại xem chiến lược. Nhưng nếu bạn thấy tài khoản bị đổi chủ, trang bị xoá không báo, báo cáo không khớp Search Console hay website nhận Manual Action, đó là lúc cần làm theo thứ tự: bảo vệ quyền truy cập, lưu bằng chứng, xuất dữ liệu, rồi mới yêu cầu giải trình.&lt;/p&gt;

&lt;p&gt;Quy trình chi tiết, kèm bảng phân biệt "SEO chưa hiệu quả" với "dấu hiệu vi phạm", mình thấy bài &lt;a href="https://manhdigital.com/blog/dau-hieu-cong-ty-seo-lua-dao" rel="noopener noreferrer"&gt;7 bước kiểm tra công ty SEO lừa đảo&lt;/a&gt; viết khá đầy đủ, đặc biệt phần không nên disavow hay xoá website theo cảm tính.&lt;/p&gt;

&lt;h2&gt;
  
  
  Đọc thêm
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nếu bạn còn đang ở bước chọn đơn vị: &lt;a href="https://manhdigital.mataroa.blog/blog/phong-van-mot-agency-seo-trong-30-phut-kich-ban-cau-hoi-theo-tung-phut/" rel="noopener noreferrer"&gt;kịch bản phỏng vấn một agency SEO trong 30 phút&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Nếu đang cầm hai báo giá lệch nhau: &lt;a href="https://hackmd.io/@manhdigital68/SyrdWk92fx" rel="noopener noreferrer"&gt;3 lý do báo giá SEO chênh nhau nhiều lần&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bạn từng gặp điều khoản nào "lạ" trong hợp đồng SEO chưa? Để lại bình luận, mình rất muốn xem thêm các trường hợp thực tế.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>marketing</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Khai báo Organization + sameAs bằng JSON-LD để AI không nhầm thương hiệu của bạn</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Sat, 24 Oct 2026 08:13:56 +0000</pubDate>
      <link>https://dev.to/manhdigital68/khai-bao-organization-sameas-bang-json-ld-de-ai-khong-nham-thuong-hieu-cua-ban-4koa</link>
      <guid>https://dev.to/manhdigital68/khai-bao-organization-sameas-bang-json-ld-de-ai-khong-nham-thuong-hieu-cua-ban-4koa</guid>
      <description>&lt;p&gt;Khi hỏi ChatGPT hay Gemini về một doanh nghiệp nhỏ, câu trả lời hay sai ở những chỗ rất cơ bản: nhầm với một công ty trùng tên, ghi sai lĩnh vực, hoặc lấy số điện thoại cũ từ một trang danh bạ nào đó. Phần lớn lỗi này không nằm ở nội dung bài viết mà ở chỗ website chưa nói rõ "tôi là ai" bằng dữ liệu có cấu trúc.&lt;/p&gt;

&lt;p&gt;Bài này đi thẳng vào phần kỹ thuật: dựng một khối JSON-LD &lt;code&gt;Organization&lt;/code&gt; có &lt;code&gt;@id&lt;/code&gt; cố định, nối với &lt;code&gt;Person&lt;/code&gt; (người sáng lập) và danh sách &lt;code&gt;sameAs&lt;/code&gt; trỏ tới các hồ sơ bên ngoài. Không có phép màu nào ở đây, nhưng đây là phần nền mà các công cụ tìm kiếm và AI dùng để ghép các mảnh thông tin về cùng một thực thể.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Vì sao cần &lt;code&gt;@id&lt;/code&gt; cố định
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@id&lt;/code&gt; là một URI định danh cho thực thể, không phải trang. Quy ước hay dùng là lấy URL trang chủ cộng một fragment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example.com/#organization
https://example.com/#founder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Khi mọi trang trên site đều trỏ về đúng &lt;code&gt;@id&lt;/code&gt; này (trong &lt;code&gt;publisher&lt;/code&gt;, &lt;code&gt;author&lt;/code&gt;, &lt;code&gt;provider&lt;/code&gt;...), bạn đang nói với parser rằng đây là một thực thể duy nhất, chứ không phải 50 tổ chức khác nhau trên 50 trang.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Khối JSON-LD tối thiểu
&lt;/h2&gt;

&lt;p&gt;Đặt trên trang chủ (và có thể lặp lại trên trang giới thiệu):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/ld+json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@context&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://schema.org&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graph&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Organization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/#organization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Công ty ABC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;logo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/logo.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dịch vụ SEO website cho doanh nghiệp nhỏ.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;founder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/#founder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contactPoint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ContactPoint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;telephone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+84-000-000-000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contactType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customer service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;areaServed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sameAs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.linkedin.com/company/abc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://github.com/abc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.youtube.com/@abc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Person&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/#founder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nguyễn Văn A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jobTitle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Founder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;worksFor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/#organization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/gioi-thieu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vài lưu ý khi điền:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; phải khớp từng chữ với tên trên Google Business Profile, hồ sơ mạng xã hội và footer website. Lệch một chữ ("ABC" và "ABC Agency") là đủ để tạo ra hai thực thể.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sameAs&lt;/code&gt; chỉ ghi hồ sơ do chính bạn quản lý và đang hoạt động. Thêm link chết hoặc hồ sơ bỏ hoang chỉ làm nhiễu.&lt;/li&gt;
&lt;li&gt;Số điện thoại, địa chỉ trong schema phải giống hệt phần hiển thị trên trang. Schema khai một đằng, HTML ghi một nẻo là lỗi rất hay gặp.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Nối các trang khác về cùng thực thể
&lt;/h2&gt;

&lt;p&gt;Trên trang bài viết, đừng khai lại &lt;code&gt;Organization&lt;/code&gt; đầy đủ. Chỉ cần tham chiếu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Article"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tiêu đề bài"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/#founder"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"publisher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/#organization"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trên trang dịch vụ, dùng &lt;code&gt;Service&lt;/code&gt; với &lt;code&gt;provider&lt;/code&gt; trỏ về &lt;code&gt;@id&lt;/code&gt; của tổ chức. Cách này giữ dữ liệu một nguồn, sửa một chỗ là đúng ở mọi nơi.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Kiểm tra trước khi deploy
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Dán HTML vào &lt;a href="https://validator.schema.org/" rel="noopener noreferrer"&gt;Schema Markup Validator&lt;/a&gt; để xem graph có parse đúng và các &lt;code&gt;@id&lt;/code&gt; có nối với nhau không.&lt;/li&gt;
&lt;li&gt;Chạy Rich Results Test của Google cho các loại có rich result (Article, FAQ...).&lt;/li&gt;
&lt;li&gt;View source (không phải Inspect) để chắc khối JSON-LD nằm trong HTML ban đầu. Nhiều crawler, kể cả một số bot AI, không chạy JavaScript, nên schema chỉ được chèn sau khi render có thể bị bỏ qua.&lt;/li&gt;
&lt;li&gt;Đối chiếu &lt;code&gt;sameAs&lt;/code&gt; với danh sách hồ sơ thật, xoá cái nào đã chết.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  5. Schema không phải là tất cả
&lt;/h2&gt;

&lt;p&gt;Schema chỉ là lời tự khai. Công cụ tìm kiếm và AI còn kiểm chứng bằng nguồn bên ngoài: hồ sơ doanh nghiệp, bài báo, diễn đàn có nhắc tên bạn với cùng một bộ thông tin. Nếu bên ngoài không có gì khớp, khai schema đẹp đến mấy cũng ít tác dụng.&lt;/p&gt;

&lt;p&gt;Mình có ghi lại phần này kỹ hơn, kèm thứ tự ưu tiên khi một website muốn được AI nhắc đúng tên, trong ghi chú &lt;a href="https://hackmd.io/@manhdigital68/H1QNmnShMx" rel="noopener noreferrer"&gt;SEO AI: những việc nên làm trước&lt;/a&gt;. Còn nếu muốn xem cách một đơn vị làm SEO AI gói phần thực thể, nội dung và nguồn bên ngoài vào chung một phạm vi, có thể tham khảo trang dịch vụ của &lt;a href="https://manhdigital.com/dich-vu/seo-ai" rel="noopener noreferrer"&gt;Mạnh Digital&lt;/a&gt;. Bài trước của mình về &lt;a href="https://dev.to/manhdigital68/checklist-ky-thuat-de-website-vua-len-google-vua-duoc-ai-trich-dan-3nlp"&gt;checklist kỹ thuật để website vừa lên Google vừa được AI trích dẫn&lt;/a&gt; đi rộng hơn, bài này chỉ tập trung vào schema.&lt;/p&gt;

&lt;p&gt;Bạn đang khai &lt;code&gt;sameAs&lt;/code&gt; cho bao nhiêu hồ sơ? Có ai từng gặp trường hợp AI nhầm thương hiệu dù schema đã đúng chưa?&lt;/p&gt;

</description>
      <category>seo</category>
      <category>schema</category>
      <category>webdev</category>
      <category>ai</category>
    </item>
    <item>
      <title>Dịch vụ SEO AI: giúp website được Google và AI nhắc tên</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Fri, 23 Oct 2026 16:48:09 +0000</pubDate>
      <link>https://dev.to/manhdigital68/dich-vu-seo-ai-giup-website-duoc-google-va-ai-nhac-ten-i9i</link>
      <guid>https://dev.to/manhdigital68/dich-vu-seo-ai-giup-website-duoc-google-va-ai-nhac-ten-i9i</guid>
      <description>&lt;p&gt;Khi khách hàng tìm giải pháp, họ không chỉ hỏi Google. Họ còn hỏi các công cụ AI như ChatGPT, Gemini hay Perplexity. Website của bạn cần được cả hai hiểu đúng thì mới được trích dẫn và đề xuất thương hiệu.&lt;/p&gt;

&lt;p&gt;Mạnh Digital cung cấp dịch vụ SEO AI, tập trung vào ba việc:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SEO tổng thể&lt;/strong&gt;: tối ưu website, nội dung và nhóm từ khóa theo sản phẩm, dịch vụ, để tìm khách hàng từ Google.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tối ưu cho AI Search&lt;/strong&gt;: cấu trúc nội dung rõ ràng, câu trả lời trực tiếp, dữ liệu có nguồn để AI dễ trích dẫn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Theo dõi và báo cáo minh bạch&lt;/strong&gt;: theo dõi thứ hạng, lượt truy cập và phạm vi công việc rõ ràng, không hứa hẹn mơ hồ.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nếu bạn muốn biết website của mình đang đứng ở đâu với Google và các công cụ AI, hãy xem trang chính để nhận tư vấn: &lt;a href="https://manhdigital.com/" rel="noopener noreferrer"&gt;https://manhdigital.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://manhdigital.com/" rel="noopener noreferrer"&gt;manhdigital.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Quy trình 20 phút đọc Search Intent trước khi viết: query SERP trang đích</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Thu, 22 Oct 2026 11:02:05 +0000</pubDate>
      <link>https://dev.to/manhdigital68/quy-trinh-20-phut-doc-search-intent-truoc-khi-viet-query-serp-trang-dich-2f3a</link>
      <guid>https://dev.to/manhdigital68/quy-trinh-20-phut-doc-search-intent-truoc-khi-viet-query-serp-trang-dich-2f3a</guid>
      <description>&lt;p&gt;Mình từng thấy khá nhiều brief content chỉ có một dòng: "keyword: X, độ dài: 2.000 chữ". Thiếu hẳn câu hỏi quan trọng nhất: &lt;strong&gt;người gõ X muốn làm gì tiếp theo?&lt;/strong&gt; Bài này là quy trình ngắn mình dùng để trả lời câu đó trước khi đặt bút, chia thành 3 bước có thể ghi thẳng vào Google Sheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bước 0: Chuẩn bị một bảng 7 cột
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;keyword&lt;/th&gt;
&lt;th&gt;giả thuyết intent&lt;/th&gt;
&lt;th&gt;content type thắng&lt;/th&gt;
&lt;th&gt;format&lt;/th&gt;
&lt;th&gt;angle&lt;/th&gt;
&lt;th&gt;SERP features&lt;/th&gt;
&lt;th&gt;trang đích + CTA&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Mỗi keyword là một dòng. Mục tiêu là cột cuối cùng: quyết định &lt;strong&gt;loại trang nào&lt;/strong&gt; sẽ nhận keyword này.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bước 1 (3 phút): Ghi giả thuyết từ modifier
&lt;/h2&gt;

&lt;p&gt;Modifier chỉ cho giả thuyết ban đầu, không phải kết luận:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"là gì", "tại sao" → thường là informational&lt;/li&gt;
&lt;li&gt;"cách", "hướng dẫn" → informational dạng hướng dẫn&lt;/li&gt;
&lt;li&gt;"tốt nhất", "so sánh", "review", "có nên" → commercial investigation&lt;/li&gt;
&lt;li&gt;"giá", "mua", "đặt", "thuê" → transactional&lt;/li&gt;
&lt;li&gt;tên thương hiệu / công cụ → navigational&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bẫy hay gặp: keyword không có modifier (ví dụ tên một sản phẩm) có thể mang nhiều intent cùng lúc. Lúc này cột giả thuyết nên ghi "hỗn hợp – chờ SERP".&lt;/p&gt;

&lt;h2&gt;
  
  
  Bước 2 (10 phút): Đọc SERP theo 3 thuộc tính
&lt;/h2&gt;

&lt;p&gt;Mở trình duyệt ẩn danh, tìm keyword, nhìn các kết quả hữu cơ đầu và ghi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Content type&lt;/strong&gt;: blog, landing page, trang sản phẩm, danh mục, video, công cụ?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Format&lt;/strong&gt;: định nghĩa, hướng dẫn từng bước, danh sách, so sánh, checklist?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angle&lt;/strong&gt;: cho người mới, chuyên sâu, cập nhật năm nay, miễn phí, nhanh?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nếu 7/10 kết quả là bài hướng dẫn, việc nhét một landing page bán dịch vụ vào gần như là đi ngược dòng. Đây là chỗ giả thuyết ở bước 1 bị xác nhận hoặc bị lật.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bước 3 (5 phút): Ghi SERP features như manh mối
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Local Pack → có nhu cầu địa phương&lt;/li&gt;
&lt;li&gt;Shopping → áp lực giao dịch&lt;/li&gt;
&lt;li&gt;Video → người dùng có thể cần xem thao tác&lt;/li&gt;
&lt;li&gt;People Also Ask → các câu hỏi phụ nên trả lời trong bài&lt;/li&gt;
&lt;li&gt;AI Overview / Featured Snippet → nên có đoạn định nghĩa, danh sách hoặc bảng dễ trích xuất&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bước 4 (2 phút): Chốt trang đích và CTA
&lt;/h2&gt;

&lt;p&gt;Đây là lớp nhiều người bỏ qua: &lt;strong&gt;business context&lt;/strong&gt;. Sau khi biết người đọc muốn gì, hỏi tiếp: trang nào trên site giúp họ làm bước tiếp theo hợp lý?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Informational → bài explainer, CTA: đọc bài liên quan, tải mẫu&lt;/li&gt;
&lt;li&gt;Commercial → bài so sánh/tiêu chí, CTA: xem case, nhận tư vấn&lt;/li&gt;
&lt;li&gt;Transactional → landing page/bảng giá, CTA: gửi brief, nhận báo giá&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nếu một mục trong bài bắt đầu phục vụ một intent khác hẳn, tách nó thành bài riêng và đặt internal link thay vì nhồi chung.&lt;/p&gt;

&lt;h2&gt;
  
  
  Một dòng ví dụ (giả định để minh họa)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;keyword&lt;/th&gt;
&lt;th&gt;giả thuyết&lt;/th&gt;
&lt;th&gt;type&lt;/th&gt;
&lt;th&gt;format&lt;/th&gt;
&lt;th&gt;angle&lt;/th&gt;
&lt;th&gt;features&lt;/th&gt;
&lt;th&gt;trang đích&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"cách chọn công ty seo"&lt;/td&gt;
&lt;td&gt;commercial&lt;/td&gt;
&lt;td&gt;blog&lt;/td&gt;
&lt;td&gt;checklist tiêu chí&lt;/td&gt;
&lt;td&gt;cho chủ doanh nghiệp&lt;/td&gt;
&lt;td&gt;PAA&lt;/td&gt;
&lt;td&gt;bài tiêu chí, CTA nhận tư vấn&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(Dòng trên là ví dụ giả định, không phải dữ liệu SERP thực tế.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Đọc thêm
&lt;/h2&gt;

&lt;p&gt;Phần phân biệt Search Intent với keyword và user insight, cùng bảng 4 loại intent kèm loại trang phù hợp, mình thấy được trình bày gọn trong bài &lt;a href="https://manhdigital.com/blog/search-intent-la-gi" rel="noopener noreferrer"&gt;Search Intent là gì và cách xác định trong 3 bước&lt;/a&gt; của Mạnh Digital. Bài này là phiên bản "biến thành bảng tính" của khung đó.&lt;/p&gt;

&lt;p&gt;Bạn đang ghi intent vào sheet hay chỉ để trong đầu? Comment cách bạn làm nhé.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>content</category>
      <category>marketing</category>
      <category>vietnamese</category>
    </item>
    <item>
      <title>Thẻ canonical là gì? Cách dùng đúng trong SEO</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Thu, 22 Oct 2026 07:28:01 +0000</pubDate>
      <link>https://dev.to/manhdigital68/the-canonical-la-gi-cach-dung-dung-trong-seo-1kp7</link>
      <guid>https://dev.to/manhdigital68/the-canonical-la-gi-cach-dung-dung-trong-seo-1kp7</guid>
      <description>&lt;p&gt;Thẻ canonical là một thẻ HTML giúp bạn nói với Google rằng: "Trong nhóm trang gần giống nhau này, đây là URL tôi muốn dùng làm bản chính."&lt;/p&gt;

&lt;p&gt;Nó thường nằm trong phần &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; của trang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"canonical"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://example.com/bai-viet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Vì sao cần canonical?
&lt;/h2&gt;

&lt;p&gt;Một trang sản phẩm có thể có nhiều địa chỉ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;URL gốc: &lt;code&gt;example.com/ao-thun&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;URL có bộ lọc: &lt;code&gt;example.com/ao-thun?mau=do&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;URL có tham số theo dõi: &lt;code&gt;example.com/ao-thun?utm_source=email&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Người dùng thấy gần như cùng một nội dung, nhưng công cụ tìm kiếm phải xử lý ba địa chỉ. Canonical giúp gom tín hiệu về một URL đại diện.&lt;/p&gt;

&lt;p&gt;Lưu ý: canonical là tín hiệu, không phải mệnh lệnh. Google vẫn có thể chọn URL khác nếu nội dung và các tín hiệu kỹ thuật mâu thuẫn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Khi nào nên dùng canonical?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;URL có tham số theo dõi.&lt;/li&gt;
&lt;li&gt;Trang danh mục tạo ra nhiều biến thể do lọc hoặc sắp xếp.&lt;/li&gt;
&lt;li&gt;Một sản phẩm nằm trong nhiều danh mục nhưng nội dung không đổi.&lt;/li&gt;
&lt;li&gt;Phiên bản in hoặc PDF lặp lại nội dung chính.&lt;/li&gt;
&lt;li&gt;Website còn biến thể http/https, www hoặc dấu gạch cuối chưa chuẩn hóa.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trang chính nên có self-canonical, tức canonical trỏ về chính nó.&lt;/p&gt;

&lt;p&gt;Đừng canonical hai trang chỉ vì cùng chủ đề. Ví dụ "Technical SEO là gì" và "Canonical là gì" liên quan nhau nhưng phục vụ nhu cầu khác nhau, nên mỗi bài nên tự canonical về chính nó.&lt;/p&gt;

&lt;h2&gt;
  
  
  Canonical, redirect và noindex khác nhau thế nào?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cơ chế&lt;/th&gt;
&lt;th&gt;Người dùng vào URL cũ&lt;/th&gt;
&lt;th&gt;Dùng khi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Canonical&lt;/td&gt;
&lt;td&gt;Vẫn xem được&lt;/td&gt;
&lt;td&gt;Nhiều URL gần giống, cần một URL đại diện&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;301 redirect&lt;/td&gt;
&lt;td&gt;Được chuyển sang URL mới&lt;/td&gt;
&lt;td&gt;URL cũ đã ngừng dùng&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noindex&lt;/td&gt;
&lt;td&gt;Vẫn xem được&lt;/td&gt;
&lt;td&gt;Không muốn trang xuất hiện trên Search&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Quy tắc nhanh: còn nhiều bản gần giống thì dùng canonical; bỏ hẳn URL cũ thì dùng redirect 301; không muốn lên Search thì dùng noindex.&lt;/p&gt;

&lt;p&gt;Robots.txt không phải công cụ canonical. Chặn crawl có thể khiến Google không đọc được thẻ canonical trên trang.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cách cài đúng
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dùng URL tuyệt đối (có https://).&lt;/li&gt;
&lt;li&gt;Chỉ có một thẻ canonical trên mỗi trang.&lt;/li&gt;
&lt;li&gt;Đích canonical phải trả HTTP 200, không redirect, không noindex.&lt;/li&gt;
&lt;li&gt;Internal link và sitemap cùng dùng URL canonical.&lt;/li&gt;
&lt;li&gt;Với PDF, có thể gửi canonical qua HTTP header:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Link: &amp;lt;https://example.com/huong-dan&amp;gt;; rel="canonical"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trên WordPress, chỉ nên dùng một plugin SEO để tạo canonical, tránh để theme, plugin và code cùng thêm thẻ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kiểm tra khi Google chọn canonical khác
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Xem source HTML, tìm &lt;code&gt;rel="canonical"&lt;/code&gt; và kiểm tra URL, số lượng thẻ.&lt;/li&gt;
&lt;li&gt;Dùng URL Inspection trong Google Search Console để so sánh canonical bạn khai báo với canonical Google chọn.&lt;/li&gt;
&lt;li&gt;Nếu hai giá trị khác nhau, tìm nguyên nhân: canonical chéo, redirect, trang mỏng, URL tham số được link nhiều, hoặc hai trang gần như trùng nội dung.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nếu lỗi lặp lại trên nhiều trang, hãy sửa ở cấp template thay vì sửa từng trang.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tóm lại
&lt;/h2&gt;

&lt;p&gt;Còn nhiều bản gần giống thì dùng canonical. Bỏ hẳn URL cũ thì redirect. Không muốn lên Search thì noindex. Chọn đúng công cụ, rồi làm cho mọi tín hiệu kỹ thuật cùng chỉ về một URL.&lt;/p&gt;

&lt;p&gt;Bài gốc đầy đủ hơn, có ví dụ và checklist: &lt;a href="https://manhdigital.com/blog/the-canonical-la-gi" rel="noopener noreferrer"&gt;Thẻ Canonical Là Gì? Cách Dùng Đúng Trong SEO&lt;/a&gt; trên Mạnh Digital.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Viết lại tờ brief SEO: 9 ô cần điền trước khi gõ chữ đầu tiên</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Wed, 21 Oct 2026 08:59:05 +0000</pubDate>
      <link>https://dev.to/manhdigital68/viet-lai-to-brief-seo-9-o-can-dien-truoc-khi-go-chu-dau-tien-3deg</link>
      <guid>https://dev.to/manhdigital68/viet-lai-to-brief-seo-9-o-can-dien-truoc-khi-go-chu-dau-tien-3deg</guid>
      <description>&lt;p&gt;Một kịch bản mình hay gặp (ví dụ minh họa, không phải một khách hàng cụ thể): chủ website nhắn cho writer "viết giúp anh bài 1.500 từ, keyword là X". Hai ngày sau bài về, câu chữ mượt, đúng chính tả. Đăng lên, ba tháng sau vẫn không ai tìm thấy.&lt;/p&gt;

&lt;p&gt;Người viết không làm sai. Họ chỉ nhận một tờ brief gồm hai thứ: keyword và số từ. Còn lại họ phải tự đoán.&lt;/p&gt;

&lt;p&gt;Dưới đây là cách mình viết lại tờ brief, theo kiểu nhật ký: mỗi lần bài hỏng, mình thêm một ô vào form.&lt;/p&gt;

&lt;h2&gt;
  
  
  9 ô cần điền trước khi viết
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Ô cần điền&lt;/th&gt;
&lt;th&gt;Câu hỏi nó trả lời&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Keyword chính&lt;/td&gt;
&lt;td&gt;Cụm từ người dùng thực sự gõ là gì?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Keyword phụ&lt;/td&gt;
&lt;td&gt;Những biến thể nào cùng intent với nó?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Intent&lt;/td&gt;
&lt;td&gt;Họ muốn học, so sánh hay mua?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Nhiệm vụ của người đọc&lt;/td&gt;
&lt;td&gt;Đọc xong họ làm được việc gì?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Vai trò URL&lt;/td&gt;
&lt;td&gt;Đây là pillar, guide hay template?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Câu trả lời bắt buộc&lt;/td&gt;
&lt;td&gt;Câu hỏi nào bài phải trả lời ngay phần đầu?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Bằng chứng&lt;/td&gt;
&lt;td&gt;Số liệu, ví dụ, nguồn nào chứng minh?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Internal link&lt;/td&gt;
&lt;td&gt;Bài này nối với trang nào, và từ trang nào trỏ tới?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;KPI sau đăng&lt;/td&gt;
&lt;td&gt;Đo bằng gì: index, hiển thị, click, vị trí?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Ô số 5 là ô bị bỏ sót nhiều nhất. Hai bài cùng tranh một intent thì tự cạnh tranh với chính mình. Mỗi URL cần một nhiệm vụ riêng.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist kỹ thuật trước khi bấm đăng
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Trang trả về HTTP 200.&lt;/li&gt;
&lt;li&gt;Có self-canonical, không bị noindex.&lt;/li&gt;
&lt;li&gt;Nội dung chính nằm trong HTML ban đầu, không phụ thuộc hoàn toàn vào JavaScript chạy sau.&lt;/li&gt;
&lt;li&gt;Schema (nếu có) khớp với nội dung hiển thị.&lt;/li&gt;
&lt;li&gt;Title, H1, meta description khác nhau giữa các URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Một lưu ý quan trọng
&lt;/h2&gt;

&lt;p&gt;Template chỉ là lan can chống bỏ sót, không phải công thức xếp hạng. Điền đủ 9 ô không đảm bảo lên top. Nó chỉ đảm bảo người viết không phải đoán, và bạn có chỗ để quay lại xem bài hỏng ở khâu nào.&lt;/p&gt;

&lt;p&gt;Bản đầy đủ có ví dụ điền sẵn: &lt;a href="https://manhdigital.com/blog/mau-bai-viet-chuan-seo" rel="noopener noreferrer"&gt;mẫu bài viết chuẩn SEO trên ManhDigital&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>contentmarketing</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Biến template bài viết chuẩn SEO thành YAML + script Python kiểm tra tự động</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Tue, 20 Oct 2026 17:13:51 +0000</pubDate>
      <link>https://dev.to/manhdigital68/bien-template-bai-viet-chuan-seo-thanh-yaml-script-python-kiem-tra-tu-dong-858</link>
      <guid>https://dev.to/manhdigital68/bien-template-bai-viet-chuan-seo-thanh-yaml-script-python-kiem-tra-tu-dong-858</guid>
      <description>&lt;p&gt;Viết content SEO theo template thì dễ quên ô này, bỏ sót ô kia. Dân kỹ thuật có một cách quen thuộc để xử lý chuyện đó: biến template thành &lt;strong&gt;dữ liệu có cấu trúc&lt;/strong&gt;, rồi viết một script nhỏ để kiểm tra. Bài này hướng dẫn từng bước làm việc đó với YAML và Python, khoảng 60 dòng code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lưu ý: script chỉ kiểm tra "đủ ô" và vài lỗi hình thức. Nó không chấm được nội dung có hữu ích hay không. Phần đó vẫn cần người biên tập.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Bước 1: Định nghĩa brief bằng YAML
&lt;/h2&gt;

&lt;p&gt;Tạo file &lt;code&gt;brief.yaml&lt;/code&gt; cho mỗi bài:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;keyword&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mẫu&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bài&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;viết&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;chuẩn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;seo"&lt;/span&gt;
&lt;span class="na"&gt;secondary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;template&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bài&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;viết&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;seo"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;informational&lt;/span&gt;        &lt;span class="c1"&gt;# informational | commercial | transactional | navigational&lt;/span&gt;
&lt;span class="na"&gt;reader&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;người&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;viết&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;mới,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;đã&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;biết&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;SEO&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;cơ&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bản"&lt;/span&gt;
&lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tự&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;lập&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;brief&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;và&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dàn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bài&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;mà&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;không&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bỏ&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sót&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;onpage"&lt;/span&gt;
&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster&lt;/span&gt;                &lt;span class="c1"&gt;# pillar | cluster | landing | tool&lt;/span&gt;
&lt;span class="na"&gt;must_answer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mẫu&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;gồm&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;những&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;phần&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;nào?"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Điền&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;brief&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;thế&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;nào?"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Kiểm&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tra&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;gì&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trước&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;khi&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;đăng?"&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mẫu&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bài&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;viết&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;chuẩn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;SEO:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;template&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;có&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ví&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dụ"&lt;/span&gt;
&lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Brief,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dàn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ý&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;heading&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;và&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;checklist&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Onpage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;điền&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;sẵn,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;kèm&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ví&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dụ&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;thật."&lt;/span&gt;
&lt;span class="na"&gt;internal_links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/blog/search-intent-la-gi"&lt;/span&gt;
&lt;span class="na"&gt;sources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Google&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Search&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Central&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;helpful&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;content"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Điểm quan trọng: &lt;code&gt;task&lt;/code&gt; và &lt;code&gt;must_answer&lt;/code&gt; là bắt buộc. Một brief chỉ có keyword và số từ là brief chưa xong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bước 2: Viết bản nháp bằng Markdown
&lt;/h2&gt;

&lt;p&gt;Bản nháp &lt;code&gt;draft.md&lt;/code&gt; dùng &lt;code&gt;#&lt;/code&gt; cho H1, &lt;code&gt;##&lt;/code&gt; cho H2. Mỗi H2 nên ứng với một câu hỏi trong &lt;code&gt;must_answer&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bước 3: Viết script kiểm tra
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# check_brief.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;

&lt;span class="n"&gt;REQUIRED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keyword&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;intent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reader&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;must_answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;brief_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;draft_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safe_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;brief_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;md&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;draft_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="c1"&gt;# 1. Brief đủ ô
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;REQUIRED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;brief thiếu: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Độ dài title/meta theo quy ước biên tập (không phải quy định của Google)
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title &amp;gt; 60 ký tự&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta &amp;gt; 160 ký tự&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Đúng một H1
&lt;/span&gt;    &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^# (.+)$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cần đúng 1 H1, đang có &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 4. Keyword bị nhồi vào heading?
&lt;/span&gt;    &lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^## (.+)$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;kw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keyword&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;stuffed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;kw&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stuffed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hơn nửa số H2 lặp keyword chính&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 5. Mỗi câu hỏi bắt buộc có H2 tương ứng (so khớp thô theo từ)
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;must_answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
        &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\w+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\w+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chưa thấy H2 trả lời: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 6. Số liệu không có nguồn (heuristic: có % mà không có link)
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;số liệu chưa dẫn nguồn: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OK: không phát hiện lỗi hình thức&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chạy thử:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pyyaml
python check_brief.py brief.yaml draft.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bước 4: Đưa vào quy trình
&lt;/h2&gt;

&lt;p&gt;Vài cách dùng thực tế:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pre-commit hook&lt;/strong&gt;: nếu nội dung nằm trong repo (Hugo, Astro, Next.js), chặn commit khi script trả mã lỗi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI&lt;/strong&gt;: chạy trong GitHub Actions cho mỗi pull request chứa file &lt;code&gt;.md&lt;/code&gt; mới, để reviewer thấy danh sách lỗi trước khi đọc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Biên tập thủ công&lt;/strong&gt;: ngay cả khi không có repo, chạy script trên bản export Markdown từ Google Docs hoặc Notion cũng đủ bắt được lỗi quên ô.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bước 5: Biết giới hạn của script
&lt;/h2&gt;

&lt;p&gt;Script này không biết:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bài có thật sự trả lời đúng ý định tìm kiếm không.&lt;/li&gt;
&lt;li&gt;Ví dụ và số liệu có chính xác không (nó chỉ phát hiện thiếu link nguồn).&lt;/li&gt;
&lt;li&gt;Mở bài có đi thẳng vào vấn đề không.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hướng dẫn về nội dung hữu ích của Google Search Central cũng không đặt ra số từ hay mật độ từ khóa cố định. Vì vậy hãy coi script như lan can chống bỏ sót, không phải công thức xếp hạng.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lấy phần template ở đâu?
&lt;/h2&gt;

&lt;p&gt;Các ô trong &lt;code&gt;brief.yaml&lt;/code&gt; ở trên được rút gọn từ &lt;a href="https://manhdigital.com/blog/mau-bai-viet-chuan-seo" rel="noopener noreferrer"&gt;bộ template bài viết chuẩn SEO của Mạnh Digital&lt;/a&gt;, trong đó có bảng giải thích từng ô brief, khung heading và checklist Onpage đầy đủ. Bạn có thể map thêm các mục checklist thành rule mới cho script, ví dụ kiểm tra alt ảnh hoặc canonical.&lt;/p&gt;

&lt;p&gt;Nếu bạn đã tự động hóa phần kiểm tra content theo cách khác, chia sẻ ở phần bình luận nhé.&lt;/p&gt;

&lt;h2&gt;
  
  
  Đọc thêm
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://telegra.ph/Vi%E1%BA%BFt-%C4%91%C3%BAng-template-SEO-m%C3%A0-b%C3%A0i-v%E1%BA%ABn-ch%C3%ACm-6-v%E1%BA%A5n-%C4%91%E1%BB%81-hay-g%E1%BA%B7p-v%C3%A0-c%C3%A1ch-s%E1%BB%ADa-10-20" rel="noopener noreferrer"&gt;6 vấn đề hay gặp khi viết theo template SEO và cách sửa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/manhdigital68/quy-trinh-20-phut-doc-search-intent-truoc-khi-viet-query-serp-trang-dich-2f3a"&gt;Quy trình 20 phút đọc Search Intent trước khi viết&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>seo</category>
      <category>python</category>
      <category>writing</category>
      <category>automation</category>
    </item>
    <item>
      <title>Checklist kỹ thuật để website vừa lên Google vừa được AI trích dẫn</title>
      <dc:creator>Mạnh Digital</dc:creator>
      <pubDate>Tue, 20 Oct 2026 08:15:33 +0000</pubDate>
      <link>https://dev.to/manhdigital68/checklist-ky-thuat-de-website-vua-len-google-vua-duoc-ai-trich-dan-3nlp</link>
      <guid>https://dev.to/manhdigital68/checklist-ky-thuat-de-website-vua-len-google-vua-duoc-ai-trich-dan-3nlp</guid>
      <description>&lt;p&gt;Bài này dành cho dev và người tự quản website. Mình tổng hợp lại cách &lt;a href="https://manhdigital.com" rel="noopener noreferrer"&gt;Mạnh Digital&lt;/a&gt; phân biệt hai lớp tối ưu: SEO website truyền thống và SEO AI (GEO/AEO). Không có trick, chỉ là những tín hiệu mà Google và các công cụ AI dùng để hiểu một trang.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hai hệ thống, một nền móng
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tiêu chí&lt;/th&gt;
&lt;th&gt;SEO website&lt;/th&gt;
&lt;th&gt;SEO AI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mục tiêu&lt;/td&gt;
&lt;td&gt;Lên top khi khách tìm trên Google&lt;/td&gt;
&lt;td&gt;Được nhắc tên, trích dẫn trong câu trả lời của AI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nơi hiển thị&lt;/td&gt;
&lt;td&gt;Google Search, Google Maps&lt;/td&gt;
&lt;td&gt;ChatGPT, Gemini, Perplexity, Copilot, Google AI Overviews&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tín hiệu chính&lt;/td&gt;
&lt;td&gt;Kỹ thuật, độ liên quan, backlink, trải nghiệm trang&lt;/td&gt;
&lt;td&gt;Thông tin thương hiệu nhất quán, câu trả lời rõ ràng, nguồn bên ngoài nhắc tới&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Chung một nền: trang được Google index tốt, và nội dung trả lời đúng câu hỏi người dùng. Nếu lớp dưới hỏng thì lớp trên cũng không đứng được.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lớp 1: indexing và kỹ thuật
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Trang quan trọng nằm trong sitemap, không bị &lt;code&gt;noindex&lt;/code&gt; nhầm.&lt;/li&gt;
&lt;li&gt;[ ] URL cũ đã 301 thì gỡ khỏi sitemap, sửa link nội bộ trỏ thẳng về URL mới.&lt;/li&gt;
&lt;li&gt;[ ] Mỗi trang có một title riêng, không bị hard-code trong template khiến CMS không đổi được.&lt;/li&gt;
&lt;li&gt;[ ] Tốc độ tải ổn trên mobile. Gói Growth của Mạnh Digital có hạng mục riêng cho tốc độ.&lt;/li&gt;
&lt;li&gt;[ ] Kiểm tra trạng thái index định kỳ trong Search Console.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lớp 2: nội dung trả lời thẳng
&lt;/h2&gt;

&lt;p&gt;AI thích đoạn văn trả lời ngay câu hỏi trong 1–3 câu đầu, sau đó mới giải thích. Gợi ý cấu trúc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H2: &amp;lt;câu hỏi thật của khách&amp;gt;
Đoạn 1: câu trả lời ngắn, có số liệu nếu có
Đoạn 2+: giải thích, ví dụ, ngoại lệ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trang chủ manhdigital.com làm điều này ở phần FAQ: "Có cam kết chắc chắn được AI nhắc tên không?" và câu đầu là "Không." Rõ ràng, dễ trích.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lớp 3: thực thể thương hiệu
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Tên, địa chỉ, số điện thoại giống hệt nhau trên website, Google Business Profile và mạng xã hội.&lt;/li&gt;
&lt;li&gt;[ ] Có trang hồ sơ người phụ trách (author/founder) với kinh nghiệm thật.&lt;/li&gt;
&lt;li&gt;[ ] Có nguồn bên ngoài nhắc tới thương hiệu: báo, diễn đàn, hồ sơ doanh nghiệp.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ví dụ thông tin nhất quán: Mạnh Digital, Tòa AZ Sky, Định Công, Hoàng Mai, điện thoại 0396 200 150.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lớp 4: đo lường
&lt;/h2&gt;

&lt;p&gt;Không đo thì không biết có tác dụng không. Search Console cho số lượt nhấp, hiển thị, vị trí; GA4 cho hành vi và chuyển đổi. Case Kho Tài Khoản trên trang chủ dùng đúng nguồn này: khoảng 193 nghìn lượt nhấp và 1,4 triệu lượt hiển thị trong 12 tháng theo ảnh GSC chụp 05/10/2026.&lt;/p&gt;

&lt;p&gt;Lưu ý: không có cách nào đo chính xác "AI nhắc tên bao nhiêu lần" qua API chính thức. Gói Strategy của Mạnh Digital có hạng mục theo dõi AI nhắc tên, nhưng chính họ cũng nói không ai kiểm soát được câu trả lời của AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeline thực tế
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tuần 1–4: sửa kỹ thuật, trang dịch vụ, thông tin thương hiệu.&lt;/li&gt;
&lt;li&gt;Sau đó: thứ hạng và khả năng được AI nhắc tên thay đổi chậm hơn, tùy ngành và độ cạnh tranh.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Khi nào nên nhờ người ngoài?
&lt;/h2&gt;

&lt;p&gt;Nếu bạn là dev, lớp 1 bạn tự làm được. Lớp 2 và 3 tốn thời gian nghiên cứu từ khóa và viết. Bảng giá tham khảo của &lt;a href="https://manhdigital.com/dich-vu/seo-tong-the" rel="noopener noreferrer"&gt;dịch vụ SEO tổng thể&lt;/a&gt; bên đó: Starter từ 9 triệu/tháng (5–10 từ khóa, 2–4 bài/tháng), Growth từ 15 triệu (15–25 từ khóa, 4–8 bài), Strategy từ 25 triệu (30–50 từ khóa, 8–12 bài). Chưa gồm VAT.&lt;/p&gt;

&lt;p&gt;Happy optimizing. Nếu có checklist hay hơn, comment bên dưới nhé.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>google</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
