← Back to documentation

DESIGN_TRUST_BADGES_AND_FRESHNESS

Compare Page Trust Badges and Freshness Indicators

Version: 1.0
Status: Draft
Issue: BUY-2590
Parent Goal: BUY-2037 Goal
Last Updated: April 2026


1. Overview

This document defines the trust-layer design for the BuyWhere comparison surface. It establishes a badge and label system that communicates data freshness, merchant coverage, and affiliate context to both AI agents and human users.

Design Principles:

  • Trust signals must be scannable at a glance (≤3 seconds)
  • Freshness context prevents misleading price displays
  • Merchant coverage signals set appropriate expectations
  • Affiliate context maintains transparency with users

2. Badge System Architecture

2.1 Badge Categories

CategoryPurposeAudience
Freshness BadgesData age and reliabilityAI agents + humans
Merchant Trust BadgesVerification and affiliate statusAI agents + humans
Coverage BadgesScope of comparisonAI agents + humans
Context BadgesSponsored/featured contextHumans primarily

2.2 Freshness Badge Taxonomy

TierAge RangeBadge ColorBadge LabelIcondata_freshness Value
Fresh< 24 hoursGreen #10B981"Fresh"Circle-fillfresh
Recent24h - 7 daysNone (no badge)recent
Stale7 - 30 daysAmber #F59E0B"Price may vary"Warning trianglestale
Very Stale> 30 daysRed #EF4444"Outdated"X circlevery_stale
UnknownNo timestampGray #6B7280"Verify price"Question marknull

2.3 Merchant Trust Badge Taxonomy

BadgeMeaningIconColorUsage
Verified MerchantIdentity confirmed by BuyWhereShield checkBlue #0066FFMerchant name in compare table
Affiliate PartnerActive commission arrangementDollar signGreen #10B981Price row or buy button
Direct LinkNo affiliate relationshipExternal linkGray #6B7280Price row
SponsoredPaid placementStarAmber #F59E0BProduct card header

2.4 Coverage Badge Taxonomy

BadgeTriggerIconColorPlacement
Full Coverage3+ retailers with pricesNonePage header
Low Coverage2 retailersAlert triangleAmber #F59E0BPage header + table
Limited Coverage1 retailerAlert octagonRed #EF4444Page header + card
No Coverage0 retailersX circleRed #EF4444Empty state

3. Freshness Indicator Design

3.1 Freshness Badge Specifications

┌─────────────────────────────────────────────────────────────┐
│  FRESHNESS BADGE SPECS                                      │
│                                                              │
│  ┌──────────────┐  ┌─────────────────┐  ┌────────────────┐   │
│  │ ● Fresh       │  │ ⚠ Price may    │  │ ✕ Outdated    │   │
│  │   12px 500   │  │   vary 12px 500 │  │   12px 500    │   │
│  └──────────────┘  └─────────────────┘  └────────────────┘   │
│                                                              │
│  Height: 20px                                               │
│  Padding: 4px 8px                                           │
│  Border-radius: 4px                                         │
│  Font: Inter 500, 12px                                     │
└─────────────────────────────────────────────────────────────┘

Visual Specs:

  • Badge height: 20px
  • Horizontal padding: 8px (space-2)
  • Border-radius: 4px (radius-sm)
  • Font: Inter 500, 12px
  • Icon size: 14px, left-aligned with 4px gap
  • Text: sentence case

3.2 Freshness Badge Colors

StateBackgroundTextIcon
Fresh#D1FAE5#065F46#10B981
Stale#FEF3C7#92400E#F59E0B
Very Stale#FEE2E2#991B1B#EF4444
Unknown#F3F4F6#6B7280#9CA3AF

3.3 Timestamp Display

Primary Format: Relative time ("Updated 2 hours ago") Fallback Format: Absolute date ("Updated Apr 15, 2026")

┌─────────────────────────────────────────────────────────────┐
│  TIMESTAMP DISPLAY                                         │
│                                                              │
│  Relative (default for < 7 days):                          │
│  "Updated 2 hours ago" — body-sm, text-muted               │
│  "Updated 3 days ago" — body-sm, text-muted                │
│                                                              │
│  Absolute (for stale/very_stale or user preference):       │
│  "Updated on Apr 15, 2026" — body-sm, text-muted           │
│                                                              │
│  Very Stale override:                                      │
│  "⚠ Verified on Apr 1 — prices may have changed"           │
│  body-sm, warning color                                     │
└─────────────────────────────────────────────────────────────┘

Specs:

  • Font: Inter 400, 14px (body-sm)
  • Color: #6B7280 (text-muted)
  • Margin-top: 4px (space-1)
  • Position: Below price in product card

3.4 Freshness in Comparison Table

┌─────────────────────────────────────────────────────────────┐
│  COMPARISON TABLE FRESHNESS DISPLAY                        │
│                                                              │
│  ┌──────────────────┬──────────┬──────────┬──────────┐     │
│  │                  │ Shopee   │ Lazada   │ Amazon   │     │
│  ├──────────────────┼──────────┼──────────┼──────────┤     │
│  │ Price            │ SGD 449 │ SGD 459  │ SGD 469  │     │
│  │                  │ ● Fresh │ ● Fresh  │ ⚠ Stale │     │
│  ├──────────────────┼──────────┼──────────┼──────────┤     │
│  │ Last Updated     │ 2h ago   │ 5h ago   │ 12d ago  │     │
│  └──────────────────┴──────────┴──────────┴──────────┘     │
│                                                              │
│  Freshness indicator: small inline badge, right of price   │
│  Timestamp: separate row below attribute name               │
└─────────────────────────────────────────────────────────────┘

4. Merchant Trust Badges

4.1 Verified Merchant Badge

Purpose: Confirms the merchant is a known, vetted entity.

┌─────────────────────────────────────────────────────────────┐
│  VERIFIED MERCHANT BADGE                                    │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  🛡️ Verified    Merchant Name                        │  │
│  │       12px 500   Inter 500, 14px, text-primary        │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                              │
│  Badge specs:                                               │
│  - Icon: Shield check, 14px, #0066FF                       │
│  - Gap: 4px between icon and text                          │
│  - Position: Left of merchant name in table               │
└─────────────────────────────────────────────────────────────┘

4.2 Affiliate Partner Badge

Purpose: Discloses active commission relationship.

┌─────────────────────────────────────────────────────────────┐
│  AFFILIATE BADGE DISPLAY                                    │
│                                                              │
│  Option A — Inline with price:                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  SGD 449 💰                                           │  │
│  │  Affiliate                                              │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                              │
│  Option B — Below buy button:                              │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  [View Deal →]                                        │  │
│  │  💰 Affiliate link — supports our site                │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                              │
│  Badge specs:                                               │
│  - Icon: Dollar sign, 12px, #10B981                       │
│  - Text: Inter 400, 11px, #10B981                          │
│  - Background: #D1FAE5, 4px padding                       │
└─────────────────────────────────────────────────────────────┘

4.3 Sponsored Badge

Purpose: Indicates paid placement or featured listing.

┌─────────────────────────────────────────────────────────────┐
│  SPONSORED BADGE                                            │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  ⭐ Sponsored                                          │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                              │
│  Badge specs:                                               │
│  - Background: #FEF3C7                                     │
│  - Text: #92400E                                           │
│  - Icon: Star, 12px, #F59E0B                              │
│  - Font: Inter 500, 11px, uppercase                       │
│  - Border-radius: 4px                                      │
│  - Position: Top-right of product card, above image        │
└─────────────────────────────────────────────────────────────┘

5. Coverage Indicators

5.1 Page-Level Coverage Header

┌─────────────────────────────────────────────────────────────┐
│  PAGE HEADER WITH COVERAGE                                  │
│                                                              │
│  Comparing: Sony WH-1000XM5 Wireless Headphones             │
│  3 products from 3 merchants              ✓ Full Coverage  │
│                                                              │
│  — OR —                                                     │
│                                                              │
│  Comparing: Sony WH-1000XM5                                 │
│  2 products from 2 merchants              ⚠ Low Coverage  │
└─────────────────────────────────────────────────────────────┘

Specs:

  • Coverage badge: Right-aligned in page title area
  • Font: Inter 500, 12px
  • Full Coverage: No badge shown (cleaner UI)
  • Low/Limited/No Coverage: Badge displayed with amber/red color

5.2 Coverage Warning Banner

For 1-retailer (Limited Coverage) state:

┌─────────────────────────────────────────────────────────────┐
│  ⚠️ LIMITED COVERAGE                                        │
│  Only 1 retailer available for this product.              │
│  Price comparison is unavailable — limited data.          │
│  [Search for alternatives →]                               │
└─────────────────────────────────────────────────────────────┘

Specs:

  • Background: #FEF3C7 (amber-50)
  • Border-left: 4px solid #F59E0B
  • Padding: 12px 16px
  • Text: Inter 400, 14px
  • Icon: Alert triangle, 16px, #F59E0B

6. Mobile Placement Guidance

6.1 Mobile Card Layout

┌─────────────────────────────────────────┐
│  [Sponsored Badge - if applicable]      │  ← Top-right corner
│  ┌───────────────────────────────────┐  │
│  │                                   │  │
│  │           Product Image          │  │
│  │            (1:1 ratio)           │  │
│  │                                   │  │
│  └───────────────────────────────────┘  │
│                                          │
│  Shopee SG  🛡️ Verified                 │  ← Merchant + trust
│  Sony WH-1000XM5 Wireless Headphones   │  ← Product name
│  ★★★★☆ (1,234 reviews)                 │  ← Rating
│                                          │
│  SGD $449.00              ● Fresh        │  ← Price + freshness
│  Updated 2 hours ago                    │  ← Timestamp
│                                          │
│  Free shipping                          │
│                                          │
│  [View Deal →]                         │
│  💰 Affiliate link                       │  ← If applicable
└─────────────────────────────────────────┘

Mobile Freshness Position:

  • Freshness badge: Right of price, same line
  • Timestamp: Below price, smaller text
  • Trust badges: Left of merchant name

6.2 Mobile Comparison Table

┌─────────────────────────────────────────┐
│  COMPARISON TABLE (Mobile)              │
│  Horizontal scroll with sticky labels   │
│                                          │
│  ┌────────────┬────────┬────────┬────┐ │
│  │ Attribute  │ Shopee │ Lazada │ ... │ │
│  ├────────────┼────────┼────────┼────┤ │
│  │ Price      │ SGD449 │ SGD459 │    │ │
│  │            │ ● Fresh│ ⚠ Stale│    │ │
│  ├────────────┼────────┼────────┼────┤ │
│  │ Merchant   │🛡️ V.   │        │    │ │
│  ├────────────┼────────┼────────┼────┤ │
│  │ Shipping   │ 2 days │ 2 days │    │ │
│  ├────────────┼────────┼────────┼────┤ │
│  │ Rating     │ ★★★★☆ │ ★★★★☆ │    │ │
│  └────────────┴────────┴────────┴────┘ │
└─────────────────────────────────────────┘

Mobile Table Specs:

  • First column: Sticky position, 100px width
  • Cell padding: 8px 12px
  • Freshness badge: Below price in same cell
  • Horizontal scroll: Shadow indicators on edges

7. Desktop Placement Guidance

7.1 Desktop Card Layout

┌─────────────────────────────────────────────────────────────────────┐
│  DESKTOP PRODUCT CARD                                               │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │  [Sponsored Badge - if applicable]                    [Image] │ │
│  │                                                        1:1     │ │
│  ├────────────────────────────────────────────────────────────────┤ │
│  │  🛡️ Verified    Shopee SG                                   │ │
│  │                                                                │ │
│  │  Sony WH-1000XM5 Wireless Headphones                          │ │
│  │  ★★★★☆ (1,234 reviews)                                      │ │
│  │                                                                │ │
│  │  SGD $449.00                                    ● Fresh       │ │
│  │  Updated 2 hours ago                                          │ │
│  │                                                                │ │
│  │  ✓ In Stock  •  Free shipping                                │ │
│  │                                                                │ │
│  │  [View Deal →]                                    💰 Affiliate  │ │
│  └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘

7.2 Desktop Comparison Table

┌─────────────────────────────────────────────────────────────────────┐
│  DESKTOP COMPARISON TABLE                                           │
│                                                                      │
│  ┌────────────┬────────────────┬────────────────┬────────────────┐  │
│  │ Attribute  │ Shopee         │ Lazada         │ Amazon         │  │
│  ├────────────┼────────────────┼────────────────┼────────────────┤  │
│  │ Price      │ SGD 449 ● Fresh│ SGD 459        │ SGD 469 ⚠ Stale│  │
│  │            │ Updated 2h ago │ Updated 5h ago │ Updated 12d ago│  │
│  ├────────────┼────────────────┼────────────────┼────────────────┤  │
│  │ Merchant   │ 🛡️ Verified   │ 🛡️ Verified   │                │  │
│  ├────────────┼────────────────┼────────────────┼────────────────┤  │
│  │ Shipping   │ 2 days         │ 2 days         │ 3-5 days       │  │
│  ├────────────┼────────────────┼────────────────┼────────────────┤  │
│  │ Rating     │ ★★★★☆ (4.5)   │ ★★★★☆ (4.2)   │ ★★★★★ (4.8)   │  │
│  ├────────────┼────────────────┼────────────────┼────────────────┤  │
│  │ Condition  │ New            │ New            │ New            │  │
│  ├────────────┼────────────────┼────────────────┼────────────────┤  │
│  │ Affiliate  │ 💰 Active      │ 💰 Active      │ — Direct       │  │
│  └────────────┴────────────────┴────────────────┴────────────────┘  │
└─────────────────────────────────────────────────────────────────────┘

Desktop Table Specs:

  • Column width: Flexible, min 120px
  • Attribute column: Fixed 140px
  • Cell padding: 12px 16px
  • Price cell: Badge right-aligned
  • Affiliate row: Icon + status text

8. Implementation Reference

8.1 Component Hierarchy

ComparePage
├── CoverageHeader
│   └── CoverageBadge (conditional)
├── ProductCard (×N)
│   ├── SponsoredBadge (conditional)
│   ├── MerchantTrustBadges
│   │   └── VerifiedBadge (conditional)
│   ├── FreshnessIndicator
│   │   ├── FreshnessBadge
│   │   └── TimestampText
│   └── AffiliateDisclosure (conditional)
└── ComparisonTable
    ├── FreshnessColumn (per merchant)
    └── AffiliateColumn (per merchant)

8.2 API Data Contract

Minimum required fields for trust layer:

interface TrustLayerData {
  // Freshness
  data_freshness: 'fresh' | 'recent' | 'stale' | 'very_stale' | null;
  last_checked: string | null; // ISO timestamp
  
  // Merchant trust
  merchant_verified: boolean;
  affiliate_status: 'active' | 'pending' | 'direct' | null;
  
  // Coverage
  retailer_count: number;
  total_retailers: number; // For percentage calculation
}

8.3 Rendering Logic

// Freshness badge rendering
function renderFreshnessBadge(freshness: string | null): BadgeConfig {
  switch (freshness) {
    case 'fresh':
      return { label: 'Fresh', color: 'green', icon: 'circle-fill' };
    case 'recent':
      return { label: '', color: 'none', icon: null }; // No badge
    case 'stale':
      return { label: 'Price may vary', color: 'amber', icon: 'warning' };
    case 'very_stale':
      return { label: 'Outdated', color: 'red', icon: 'x-circle' };
    default:
      return { label: 'Verify price', color: 'gray', icon: 'help-circle' };
  }
}

// Coverage badge rendering
function renderCoverageBadge(count: number): BadgeConfig {
  if (count >= 3) return null; // No badge for full coverage
  if (count === 2) return { label: 'Low Coverage', color: 'amber' };
  if (count === 1) return { label: 'Limited Coverage', color: 'red' };
  return { label: 'No Coverage', color: 'red' };
}

9. QA Acceptance Criteria

9.1 Freshness Badge Testing

Test CaseExpected Result
Product updated < 24h agoGreen "Fresh" badge displayed
Product updated 24h-7d agoNo badge displayed
Product updated 7-30d agoAmber "Price may vary" badge displayed
Product updated > 30d agoRed "Outdated" badge displayed
No timestamp availableGray "Verify price" badge displayed
All products freshHeader shows "Full Coverage" with no badge

9.2 Trust Badge Testing

Test CaseExpected Result
Verified merchantShield check icon displayed
Active affiliateDollar sign icon + "Affiliate link" text
Sponsored listingStar badge in top-right of card
Direct (non-affiliate)No affiliate badge displayed

9.3 Coverage Badge Testing

Test CaseExpected Result
3+ retailersNo badge, clean header
2 retailersAmber "Low Coverage" in header
1 retailerRed "Limited Coverage" in header + warning banner
0 retailersRed "No Coverage" + empty state message

9.4 Accessibility Testing

  • Freshness badges have aria-label with full text ("Data refreshed 2 hours ago")
  • Color is not sole indicator (icon + text always paired)
  • Warning badges meet 3:1 contrast ratio
  • Screen reader announces: "Price $449, Fresh data, Updated 2 hours ago"
  • Touch targets minimum 44px × 44px on mobile

10. Implementation Checklist

Backend (Priority Order)

  • Populate data_freshness field based on updated_at timestamp
  • Populate merchant_verified boolean from merchant registry
  • Populate affiliate_status from affiliate system
  • Add last_checked timestamp to all compare responses
  • Compute retailer_count and total_retailers for meta

Frontend (Priority Order)

  • Implement FreshnessBadge component
  • Implement VerifiedMerchantBadge component
  • Implement AffiliateBadge component
  • Implement SponsoredBadge component
  • Implement CoverageBadge component
  • Add coverage warning banner for 1-retailer state
  • Add freshness column to comparison table
  • Add affiliate row to comparison table
  • Test all badge states and transitions
  • Verify WCAG 2.1 AA compliance

Design Handoff

  • Export Figma components for all badge types
  • Document color tokens for all badge states
  • Confirm spacing and typography specs
  • Review with Head of Design (Iris)

Appendix: Badge Quick Reference

Freshness Badges

  ● Fresh          ⚠ Price may vary    ✕ Outdated      ? Verify price
  #D1FAE5/#065F46 #FEF3C7/#92400E    #FEE2E2/#991B1B #F3F4F6/#6B7280

Trust Badges

  🛡️ Verified     💰 Affiliate     ⭐ Sponsored
  #0066FF        #10B981          #F59E0B

Coverage Badges

  ✓ Full Coverage  ⚠ Low Coverage  ⚠ Limited Coverage
  (no badge)       #FEF3C7/#92400E #FEE2E2/#991B1B

Design specification for BUY-2590. For questions, tag the design team (Iris) or engineering lead.