The FTC Endorsement Guides (revised 2023) explicitly require that "Verified Purchase" or equivalent indicators be truthful — displaying the badge for reviews from non-buyers is a deceptive endorsement. Beyond legal risk, unverified reviews mixed into the same display as genuine buyer reviews dilute trust: a product with 100% "Verified Purchase" badges where the badge is just hardcoded to true will have the label completely reverse-fired when a single fraudulent review is exposed publicly. The verified_purchase check must reach into order history at submission time to have any meaning; a database field alone without that query is cosmetic.
Medium because a hardcoded or query-free verified-purchase badge violates FTC endorsement guidelines and misleads shoppers without allowing unauthorized data access.
Check order history at review submission time in api/reviews/submit and expose the badge in components/ReviewItem.tsx.
ALTER TABLE reviews ADD COLUMN verified_purchase BOOLEAN NOT NULL DEFAULT FALSE;
// api/reviews/submit
const purchase = await db.orders.findFirst({
where: { user_id: userId, product_id: productId, status: 'completed' }
})
await db.reviews.create({
data: {
verified_purchase: purchase !== null,
// ...
}
})
// components/ReviewItem.tsx
{review.verified_purchase && (
<span className="badge-verified" aria-label="Verified Purchase">
✓ Verified Purchase
</span>
)}
Never set verified_purchase: true on insert without the order lookup — the badge only has legal standing if it reflects an actual completed transaction.
ID: ecommerce-reviews.moderation-trust.verified-purchase
Severity: medium
What to look for: Count the number of verification layers: (1) verified_purchase boolean field in the reviews database schema, (2) logic in the review submission handler that queries order history to set the flag, (3) visual badge/indicator in the review display component that distinguishes verified from unverified reviews. Report: X of 3 verification layers present.
Pass criteria: At least 2 of 3 verification layers are implemented: the database has a verified_purchase field, the submission handler checks order history to set it, and the display component shows a visible "Verified Purchase" badge or distinguishing indicator for reviews from actual buyers.
Fail criteria: Fewer than 2 of 3 verification layers exist, or all reviews display "Verified Purchase" regardless of actual purchase history (hardcoded badge).
Skip (N/A) when: The project has no order/purchase system or no auth system (cannot correlate users to purchases).
Detail on fail: "1 of 3 verification layers found (database field exists). Submission handler does not check order history. Display has no visual badge." or "All reviews render 'Verified Purchase' badge — field is hardcoded to true on insert without checking orders."
Remediation: Add purchase verification in api/reviews/submit and display the badge in components/ReviewItem.tsx:
ALTER TABLE reviews ADD COLUMN verified_purchase BOOLEAN DEFAULT FALSE;
// On review submission, check if user purchased the product
const purchase = await db.orders.findFirst({
where: {
user_id: userId,
product_id: productId,
status: 'completed'
}
})
const review = await db.reviews.create({
data: {
verified_purchase: !!purchase,
// ...
}
})
// Display component
{review.verified_purchase && <span className="badge">✓ Verified Purchase</span>}