Vì sao AI nói bạn hết hàng trong khi hàng vẫn còn

Jump to section›
Tóm tắt nhanh: Một store nội thất ở Mỹ có 30.855 sản phẩm đang nằm trong kho và một website nói rõ điều đó. Bốn AI shopping agent vẫn nói với người mua là đã hết hàng. Store không xui, và agent cũng không hỏng. Tình trạng còn hàng mà mấy con máy đọc và tình trạng còn hàng mà con người thấy là hai con số khác nhau sống trên cùng một trang. Availability không phải bài toán ranking — nó là bài toán structured-data, và nó hỏng một cách im lặng.
#Con người và agent đọc hai phiên bản "còn hàng" khác nhau
Mở một trang sản phẩm của bạn ra. Bạn thấy badge xanh "Còn hàng", một mức giá, nút Thêm vào giỏ. Đó là DOM — trang sau khi JavaScript của bạn đã chạy trong một trình duyệt thật.
Một AI shopping agent gần như không bao giờ thấy cái đó. Nó đọc trang khi tới qua đường truyền: HTML server-render và bất kỳ khối JSON-LD Product/Offer nào nhúng trong đó — phiên bản tồn tại trước khi JavaScript vẽ bất cứ thứ gì vào. Nếu badge "Còn hàng" được JS client-side vẽ, còn HTML thô hoặc JSON-LD vẫn mang giá trị cũ như BackOrder, agent tin cái nó đọc được trước. Rồi nó lặp lại cho người mua: "Có vẻ món đó đang backorder — đây là vài lựa chọn khác."
Agent đọc trang chính xác. Chính cái trang mới đang kể hai câu chuyện khác nhau cho hai người đọc khác nhau.
Điều này giả định agent đã tới được trang của bạn. Nếu nó không phân giải được URL, không markup nào ở đây được đọc cả — đó là tầng redirect-map bên dưới, điều kiện tiên quyết cho mọi thứ ở đây. Bài này nói về câu hỏi kế tiếp: khi agent đã tới, nó có đọc đúng sự thật không?
#Availability thực sự nằm ở đâu
Trong structured data, tình trạng tồn kho không phải văn xuôi — nó là một field cụ thể với một giá trị được kiểm soát. Trên một schema.org/Offer, đó là availability, và nó nhận một giá trị URL từ một tập cố định:
https://schema.org/InStockhttps://schema.org/OutOfStockhttps://schema.org/BackOrderhttps://schema.org/PreOrderhttps://schema.org/LimitedAvailability
Giá trị đó chính là cái agent trích dẫn khi người mua hỏi "lấy được món này không?" Và agent đọc theo tầng, theo thứ tự tin cậy: JSON-LD Product/Offer trước, rồi microdata, rồi mới tới text hiển thị trong HTML. Khi các tầng khớp nhau, mọi thứ ổn. Khi chúng lệch nhau — JSON-LD nói một đằng, text trên trang nói một nẻo — agent phải đoán cái nào là chính thức, và nó thường đoán sai.
Đây là lý do "nhìn trên màn hình thấy đúng" không cứu được bạn. Cái badge con người thấy là thứ cuối cùng agent tin, và thường là thứ nó không bao giờ thấy. Nếu JSON-LD của bạn ship một availability cũ, thì một badge JavaScript hoàn toàn đúng cũng vô hình với con máy đang đọc bạn.
#Ba bug làm availability đọc sai
Đây là những mẫu ở mức cơ chế — những hình dạng lặp lại chúng tôi thấy khi đọc các storefront public, không phải số đo trên một store cụ thể nào.
#1. Tồn kho do JavaScript vẽ, HTML và JSON-LD để cũ
Cái hay gặp nhất. Server ship HTML (và thường cả JSON-LD) với một giá trị availability mặc định hoặc cũ, còn tình trạng thật được fetch và vẽ vào bằng JavaScript client-side sau khi load. Con người nhận badge đã sửa vì trình duyệt của họ chạy JS. Agent đọc các byte được ship và rời đi trước khi JS kịp chạy. Bất cứ giá trị cũ nào nằm trong HTML là câu trả lời nó mang theo. Đây đúng là ca Home Elegance bên dưới.
#2. JSON-LD trùng hoặc mâu thuẫn
Hai node Product trên một trang — một từ theme, một từ SEO app — mỗi cái mang Offer riêng. Agent phải resolve cái nào là thật, và không có gì bảo đảm nó chọn cái có availability đúng. Cách sửa là dedup: một graph Product/Offer trên mỗi trang, với @id ổn định để node không mơ hồ. (Đây cũng là cùng loại vệ sinh markup chi phối việc resolve brand và AggregateRating.)
#3. Một câu boilerplate vô điều kiện trong template
Một template in "Ships in 4–6 weeks" hoặc "This item is backordered" vào HTML cho mọi sản phẩm, bất kể tồn kho thật, vì điều kiện lẽ ra phải chặn nó chưa bao giờ được nối. Con người lướt qua. Agent đọc nó như trạng thái chính thức của sản phẩm và trích dẫn lại — kể cả khi hệ thống tồn kho của bạn nói món đó đang nằm trên kệ.
Cả ba đều sửa được ở tầng markup/render. Không cái nào cần đụng tới checkout, thiết kế theme, hay ERP của bạn.
#Một ca thật: Home Elegance USA
Home Elegance USA là một nhà bán lẻ nội thất trên Shopify ở Mỹ với 30.855 sản phẩm, tất cả đều hiện còn hàng trên site. Chúng tôi test availability theo cách nhàm chán, lặp lại được: năm câu hỏi mua trên bốn agent — ChatGPT, Gemini, Perplexity, Claude — 20 ô, chấm điểm và ghi ngày.
- Baseline: 4/4 agent nói với người mua rằng nội thất đang còn hàng là backorder hoặc không có sẵn. 0/4 xác nhận "Còn hàng."
- Nguyên nhân: bug #1 ở trên — một câu backorder render vô điều kiện trong HTML, với tình trạng tồn kho thật được vẽ vào sau bằng JavaScript.
- Các fix, trong khoảng mười ngày: làm câu backorder có điều kiện và server-render tình trạng tồn kho thật; dedup JSON-LD và gắn lại
brandqua một@idổn định; nốiAggregateRatinglive; thêm FAQ schema. Tất cả là việc về tính đúng đắn, tất cả ở tầng markup. - Sau đó: 0/4 agent nói backorder; 3/4 xác nhận rõ ràng "Còn hàng."
Và phần chúng tôi nói thẳng ra một cách có chủ đích: thứ hạng category đứng yên (khoảng 4/12 → 3–4/12). Đây là fix về tính đúng đắn, không phải fix ranking. Làm cho agent mô tả bạn chính xác là một cơ chế khác với làm cho nó chọn bạn trong một câu trả lời cạnh tranh — cái thứ hai chạy trên review, entity authority, và corroboration từ bên thứ ba theo một cung thời gian dài hơn. Ai claim thắng ranking trong mười ngày từ một fix template là đang bán cho bạn thứ gì đó.
Bản tường thuật đầy đủ của ca này — triệu chứng, nguyên nhân, năm fix, before/after có ghi ngày — ở đây: Bốn AI Agent nói với người mua rằng store nội thất này đã hết hàng, và trang case đã được client duyệt ở luma-e.com/work/home-elegance-usa-ai-agent-commerce-readiness-2026.
#Làm sao biết fix của bạn thực sự có tác dụng
Đo nó theo cách bạn sẽ đo bất cứ thứ gì bạn muốn tin: một bộ câu hỏi mua cố định, hỏi trên các agent quan trọng, chấm điểm và ghi ngày, trước và sau. Nhàm chán, lặp lại được, có ngày. Nếu nó không được viết xuống kèm một cái ngày bên cạnh, nó không phải kết quả — nó là cảm giác.
Bạn có thể chạy phiên bản nhỏ nhất của việc này tại nhà ngay bây giờ. Chọn sản phẩm bán chạy nhất. Hỏi ChatGPT xem nó còn hàng không, diễn đạt đúng như một người mua thật sẽ hỏi — "món [sản phẩm] có đặt được không?" Rồi so câu trả lời với cái hệ thống tồn kho của bạn thực sự nói. Nếu chúng lệch nhau, bạn vừa tìm ra khoảng trống, và gần như chắc chắn đó là một trong ba bug ở trên.
#Cách sửa, không cần dựng lại
- Server-render tình trạng tồn kho thật vào HTML. Đừng để JavaScript client-side là nguồn sự thật duy nhất cho availability. Giá trị nằm trong các byte là giá trị agent mang theo.
- Dedup JSON-LD. Một node
Product/Offerđúng trên mỗi trang, với@idổn định để agent không có gì để resolve nhầm. - Map
Offer.availabilityđúng trạng thái thật.InStock/OutOfStock/BackOrder/PreOrderở đúng chỗ mỗi cái áp dụng — và xóa câu backorder vô điều kiện. - Giữ các tầng đồng bộ. Giá, currency,
AggregateRatingvà availability phải nói cùng một điều trong HTML và trong JSON-LD. Sự lệch giữa các tầng chính là cái làm agent phải đoán.
Availability không phải một cái badge — nó là một giá trị mấy con máy đọc trước khi khách của bạn kịp thấy site. Làm cho phiên bản agent đọc khớp với phiên bản đang đúng. Mọi thứ khác trong "AI visibility" đến sau cái đó. Nếu bạn chưa từng kiểm tra, phép thử nhanh nhất là miễn phí: hỏi ChatGPT xem sản phẩm bán chạy nhất của bạn còn hàng không, theo cách một người mua thật sẽ hỏi — và xem nó trả lại cho bạn cái nào trong hai câu trả lời của bạn.
Gửi một URL store và chúng tôi sẽ chạy một lượt đọc AI-correctness async miễn phí: chúng tôi hỏi các AI agent thật về sản phẩm của bạn, chạy đúng bài test 20 ô availability, và gửi lại một punch-list nêu tên chính xác agent nào đang đọc sai tồn kho của bạn và chỗ nào markup lệch với sự thật: luma-e.com/ai-readiness. Không cần call.