figma guide

Designing recently viewed products UI in Figma: rails, persistence, and handoff

Design recently viewed product rails, homepage strips, and empty states in Figma with local vs server persistence, card reuse, and Dev Mode specs for PDP recirculation.

Published
Updated
Jun 26, 2026
Read time
6 min
Level
Beginner

Quick answer

Recently viewed products help shoppers return to items they already inspected without relying on browser back or search. Show a horizontal scroll rail of product cards (usually 4–12 items, newest first) on the homepage, cart empty state, PDP footer, or account dashboard. Persist the list in local storage for guests and account history for logged-in users—cap at 20 SKUs and dedupe so the same PDP visit does not create duplicate cards. Hide the module when the list is empty. Start from the Figma guides hub.


Who this is for

  • Product designers improving return visits and reducing “where was that product?” friction.
  • Design system teams reusing PLP card components in a slim RecentlyViewedCard variant.
  • Engineers syncing view events from PDP, handling GDPR consent, and merging guest → logged-in history on sign-in.

Where recently viewed appears

SurfaceComponentPurpose
HomepageRecentlyViewedRailResume session after tab close
PDP below buy boxSame rail, compactCross-sell without algorithm
Empty cartRail + CTAFill cart from history
404 / search no resultsOptional railRecovery path
Account dashboardFull gridLonger history, remove item action
Checkout confirmationUsually skipUse recommendations instead

Verdict: recently viewed is behavioral recall, not personalized ML. Keep it separate from “You may also like” so analytics and merchandising rules stay clear.


RecentlyViewedRail anatomy

PartSpecNotes
Section header”Recently viewed” + optional “Clear all”Sentence case; not “RECENTLY VIEWED”
Card trackHorizontal scroll, snap optionalSame width as recommendations row
CardImage, title, price, optional sale badgeReuse PLP card at 160–200px width
Nav arrowsDesktop only when overflowHide on touch devices
Empty stateHidden section or placeholderNo rail DOM when length = 0
Privacy linkFooter microcopy optional”Based on your browsing on this device”
RecentlyViewedRail
├── Variant: density=compact | standard
├── Variant: state=populated | empty | loading
├── Property: maxItems=12
├── Property: showClearAll=true | false
└── Layers:
    ├── SectionHeader
    ├── ScrollTrack
    │   └── RecentlyViewedCard × n
    └── NavArrowPrev / NavNext

Use Auto Layout horizontal gap 12–16px. Cards should not shrink below min width—overflow scrolls instead of squashing.


Card content comparison

FieldRecently viewed cardFull PLP card
ImageYesYes
Title2-line clamp2-line clamp
PriceCurrent + saleSame pricing tokens
RatingOptionalOften shown on PLP
Quick viewOptionalCommon on PLP
WishlistOptional iconCommon
Variant swatchesUsually hiddenSometimes shown
Remove (×)Account view onlyN/A

Rule: price and availability must be live at render—stale sale prices in history erode trust. Show out-of-stock overlay if SKU unavailable.


Persistence and privacy

User typeStorageMerge on login
GuestlocalStorage / cookiePush to account API on auth
Logged inServer-side listDedupe by product ID, keep newest
GDPR / consentBlock until analytics consentDocument in legal frame
IncognitoSession onlyClear on tab close
B2B catalogMay disable for shared devicesProduct setting

Handoff note: dedupe on view—re-visiting PDP moves item to front, does not duplicate. Cap list length server-side to prevent unbounded payloads.


Layout comparison

PlacementBest forDesign notes
Homepage mid-pageHigh traffic storesBelow hero, above categories
PDP accordion footerLong considerationCollapse when only 1 item
Cart drawer footerImpulse addMax 4 cards visible
Full-width bandDesktop homepageMatch product listing grid gutters
Sidebar widgetLegacy layoutsAvoid on mobile

On mobile PDP, place the rail below reviews and above recommendations—do not push primary buy box below fold.


Interaction states

StateTriggerUI
HiddenZero items in historySection not rendered
LoadingFirst paint hydrating storageSkeleton cards × 4
Populated≥1 view eventFull rail
Item removedUser taps × on account pageAnimate out; persist
Clear allHeader linkConfirm modal optional
Stale productDiscontinued SKUGray card + “No longer available”

Prototype populated → remove one item → clear all on account dashboard frame.


Sync with other modules

ModuleRelationship
RecommendationsSeparate section; do not interleave cards
Compare productsCard may include compare checkbox
WishlistIndependent heart state
Quick viewOptional on rail cards
SearchHistory does not replace search

If the same product appears in both recently viewed and recommendations, allow duplicate—different sections, different intent. Do not dedupe across sections in UI unless product asks explicitly.


Handoff checklist

ItemDev Mode annotation
View eventFire on PDP product_view with id + timestamp
List APIGET /recently-viewed or client-only merge
Max itemsDefault 12 display, 20 stored
SortviewedAt descending
Card clickNavigate to PDP; same tab
ImageUse current catalog thumbnail URL
Price APIFresh on each rail render
Analyticsrecently_viewed_impression, recently_viewed_click, recently_viewed_clear
a11yRegion label aria-label="Recently viewed products"
Reduced motionNo auto-scroll carousel

Use Dev Mode checklist and responsive breakpoints for card count at 375 / 768 / 1280px.


Common mistakes

MistakeWhy it hurtsFix
Showing empty railWasted spaceHide section when length = 0
Stale sale pricesCheckout surpriseFetch live price on render
Duplicates after re-viewClutterMove-to-front dedupe
Same module as recommendationsAnalytics blurSeparate headings and APIs
Huge history on shared tabletPrivacySession cap + clear control
Autoplay scrollMotion sicknessManual scroll only
Full PLP card in narrow railOverflowSlim RecentlyViewedCard variant

  1. Finalize PLP ProductCard component with price and image tokens.
  2. Create RecentlyViewedCard slim variant (drop swatches, optional quick view).
  3. Build RecentlyViewedRail with header, track, and desktop arrows.
  4. Design empty (hidden) and loading skeleton states.
  5. Place rails on homepage, PDP footer, and empty cart frames.
  6. Add account “Browsing history” page with remove + clear all.
  7. Spec view event, dedupe, and cap in Dev Mode.
  8. Prototype scroll and card click → PDP on mobile frame.

FAQ

Recently viewed vs recommendations?

Recently viewed = SKUs the user already opened. Recommendations = algorithm or merchandising rules. Never label one as the other.

Show on checkout?

Usually no—checkout should minimize distraction. Exception: abandoned cart recovery emails, not live checkout UI.

Include in quick view?

Quick view opens from PLP; viewing still counts toward history. No need for a mini rail inside quick view.

GDPR: is this personal data?

Browsing history can be personal data in the EU. Gate persistence behind consent and offer clear in account settings.


Next steps

Share on X

§ Keep reading

Related guides.