What happened
amz verify reported search_page1 moved 17 unread regions, was 15 against a ledger taken on 2026-08-17. Two named regions have appeared on /s since that capture that no field reads:
+ s-coupon-component
+ s-impression-counter
s-impression-counter is analytics and should stay unread. s-coupon-component is a coupon badge on the search card, and it carries text worth having. Pulled from a cached page of https://www.amazon.com/s?k=mechanical+keyboard:
VND 1,572,038 Save 24% 24% off coupon applied
VND 3,667,390 Save VND 262,050 VND 262,050 off coupon applied
Both shapes are there, a percentage and an absolute amount, which is the same pair the detail page carries.
Why it matters
Card in amz/types.go has price, list_price, badge and prime but no coupon slot, so a search result with a clipped coupon is currently indistinguishable from one without. That makes the cheapest-first ordering wrong for anyone comparing on real cost, because the card price is the pre-coupon price and the saving is only stated in a region nothing reads.
The detail page already models this. amz/fields.go:107 declares coupon at LevelRegion over couponsInBuybox and promoPriceBlockMessage, and it lands in Offer.Coupon as a *Coupon with a Display string and provenance. The search card should carry the same type rather than a second shape.
Suggested shape
Add to Card:
// Coupon is the clippable coupon badge on the card, when the grid shows one.
Coupon *Coupon `json:"coupon,omitempty"`
Read it from s-coupon-component at LevelRegion, keeping the badge text verbatim in Display the way the buy box does, so a wrong parse stays recoverable. Then regenerate the ledger with go test ./amz/ -run TestCaptureLedger -update so search_page1 goes back to 17 unread minus the one now read, and add a capture that has a coupon card in it, since none of the four search captures did on the capture date.
Not a regression, for the record
The same verify run also reported product_simple worse 29 fields set, was 30. That one was a stale cache entry, not a page change: the cached copy was missing ImageBlockATF and so lost images. A live refetch yields 30 fields, matching the ledger exactly, and go test ./amz/ -run TestCaptureLedger passes against the stored captures. Nothing to do there.
What happened
amz verifyreportedsearch_page1 moved 17 unread regions, was 15against a ledger taken on 2026-08-17. Two named regions have appeared on/ssince that capture that no field reads:s-impression-counteris analytics and should stay unread.s-coupon-componentis a coupon badge on the search card, and it carries text worth having. Pulled from a cached page ofhttps://www.amazon.com/s?k=mechanical+keyboard:Both shapes are there, a percentage and an absolute amount, which is the same pair the detail page carries.
Why it matters
Cardinamz/types.gohasprice,list_price,badgeandprimebut no coupon slot, so a search result with a clipped coupon is currently indistinguishable from one without. That makes the cheapest-first ordering wrong for anyone comparing on real cost, because the card price is the pre-coupon price and the saving is only stated in a region nothing reads.The detail page already models this.
amz/fields.go:107declarescouponatLevelRegionovercouponsInBuyboxandpromoPriceBlockMessage, and it lands inOffer.Couponas a*Couponwith aDisplaystring and provenance. The search card should carry the same type rather than a second shape.Suggested shape
Add to
Card:Read it from
s-coupon-componentatLevelRegion, keeping the badge text verbatim inDisplaythe way the buy box does, so a wrong parse stays recoverable. Then regenerate the ledger withgo test ./amz/ -run TestCaptureLedger -updatesosearch_page1goes back to 17 unread minus the one now read, and add a capture that has a coupon card in it, since none of the four search captures did on the capture date.Not a regression, for the record
The same verify run also reported
product_simple worse 29 fields set, was 30. That one was a stale cache entry, not a page change: the cached copy was missingImageBlockATFand so lostimages. A live refetch yields 30 fields, matching the ledger exactly, andgo test ./amz/ -run TestCaptureLedgerpasses against the stored captures. Nothing to do there.