# Helpful vote or "was this helpful?" mechanism is displayed

- **Pattern:** `ab-001209` (`ecommerce-reviews.display-ux.helpful-votes`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001209
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001209)

## Why it matters

Helpful-vote mechanisms surface the reviews with the highest signal-to-noise ratio, so shoppers reach useful content faster and conversion climbs. Without votes, long-form detailed reviews sit next to one-line "love it" posts with no way to distinguish quality; community ranking is the cheapest moderation layer that exists. Vote data also feeds the "Most Helpful" sort (WCAG-adjacent discoverability) and trains future review-ranking models.

## Severity rationale

Low because reviews remain readable without votes, but the sort-by-helpful path and community quality ranking are unavailable.

## Remediation

Add a `helpful_votes` integer column to the reviews table, expose a POST route at `api/reviews/[id]/helpful` that increments the counter (rate-limited per user), and render a `components/HelpfulVote.tsx` button beneath each review displaying the current count:

```tsx
const handleHelpful = async () => {
  await fetch(`/api/reviews/${reviewId}/helpful`, { method: 'POST' })
  setVotes(v => v + 1)
}
```

Block duplicate votes from the same user by storing a `(user_id, review_id)` join row.

## Detection

- **ID:** `helpful-votes`
- **Severity:** `low`
- **What to look for:** Enumerate all interactive elements in the review display component. Classify whether any element functions as a helpful-vote mechanism (thumbs up/down, "Was this helpful?" button, upvote counter). Count the number of vote-related database fields or API endpoints.
- **Pass criteria:** At least 1 helpful-vote mechanism (button, thumbs up/down, or "Was this helpful?" prompt) is visible on each review, backed by at least 1 database field (e.g., `helpful_votes` column) and at least 1 API endpoint that records the vote.
- **Fail criteria:** No helpful-vote mechanism exists in the review display component, or a vote button renders but has no backend support (no API endpoint or database field).
- **Skip (N/A) when:** The project has fewer than 5 total reviews or no review display component exists.
- **Detail on fail:** `"No helpful-vote button or mechanism found in ReviewItem component. 0 vote-related API endpoints. Users cannot indicate which reviews are useful."`
- **Remediation:** Add helpful voting in `components/HelpfulVote.tsx` with an API route at `api/reviews/[id]/helpful`:

  ```tsx
  // components/HelpfulVote.tsx
  export function HelpfulVote({ reviewId, initialVotes }) {
    const [votes, setVotes] = useState(initialVotes)

    const handleHelpful = async () => {
      await fetch(`/api/reviews/${reviewId}/helpful`, { method: 'POST' })
      setVotes(votes + 1)
    }

    return (
      <button onClick={handleHelpful} className="helpful-btn">
        👍 Helpful ({votes})
      </button>
    )
  }
  ```

---

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-001209
