Live Social Proof Bar

Social proof

Show live activity

Surface real-time booking signals so visitors feel the momentum — and convert faster.

Live Activity
Verified data

14 people are looking at this right now

Offer ends in

—

Maria from Madrid just booked this

2 min ago

$180$129
Save $51 (28%)

In high demand! Booked 23 times in the last 6 hours

Only 2 spots left at this price
Limited
Secure payment
Free cancellation
Best price guarantee
9 people viewing right now
+5
4.9from 2,847 reviews
Peak booking timeNow
About this block

Live Social Proof BarPRO

Booking.com-style social proof ticker with rotating messages: live viewers, recent bookings, scarcity alerts, and location-based activity. Animated transitions, urgency indicators, and trust signals that boost conversion.

Booking13: Live Social Proof Bar

A Booking.com-style social proof panel that rotates a single animated ticker message (viewers, recent bookings, scarcity, location, or trending, each keyed to its own icon and color) on a timed interval with clickable dot navigation, stacked beneath a live "Live Activity" header and above a column of optional conversion cards: a per-second countdown, a recent-booking toast, a struck-through price comparison, a high-demand strip, an urgency alert, a three-column trust strip, a viewers avatar stack, a reviews summary, and a 24-hour hourly-bookings bar chart with per-bar tooltips.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/booking13?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/booking13?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/booking13.tsx, plus the avatar, badge, and tooltip shadcn/ui primitives it uses for the viewer/review avatar stacks, the section and price badges, and the hourly heat-chart tooltips.

Quick start

The installed file exports booking13Demo alongside the block: the exact props behind the preview above. Spread it to get a working social proof bar in one line.

tsx
import { Booking13, booking13Demo } from "@/components/beste/block/booking13";

export default function Page() {
  return <Booking13 {...booking13Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Booking13 } from "@/components/beste/block/booking13";

export default function Page() {
  return (
    <Booking13
      badge={{ label: "Social proof", variant: "secondary" }}
      heading="Show <strong>live activity</strong>"
      interval={4000}
      messages={[
        { type: "viewers", text: "{highlight} people are looking right now", highlight: "14" },
        { type: "scarcity", text: "Only {highlight}", highlight: "2 slots left", time: "for your date" },
      ]}
      priceComparisonVariant={{ currency: "$", originalPrice: 180, currentPrice: 129, saveLabel: "Save" }}
      countdownVariant={{ label: "Offer ends in", endsAt: "2026-07-13T09:00:00Z", expiredLabel: "Offer ended" }}
      labels={{ liveActivityLabel: "Live Activity", verifiedDataLabel: "Verified data" }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string; variant?: "default" | "secondary" | "outline" }–Section eyebrow badge above the heading
headingstring–Section heading, supports inline <strong>
descriptionstring–Optional subheading paragraph under the heading
messagesProofMessage[][]Rotating ticker messages cycled in the live panel
intervalnumber4000Milliseconds between automatic ticker advances
highDemandVariantHighDemandVariant–Flame "in high demand" card
urgencyVariantUrgencyVariant–Rose urgency strip with a badge
viewersVariantViewersVariant–Viewers count row with an avatar stack
countdownVariantCountdownVariant–Per-second countdown card
recentBookingToastRecentBookingToast–Single "just booked" toast card
priceComparisonVariantPriceComparisonVariant–Struck-through price with a computed savings badge
trustStripVariantTrustStripVariant–Three-column icon+label trust strip
reviewsVariantReviewsVariant–Star rating and review-count summary
heatVariantHeatVariant–24-hour hourly-bookings bar chart
labelsBooking13Labels{}Header labels (liveActivityLabel, verifiedDataLabel)
classNamestring–Extra classes for the outer <section>
ts
type ProofType = "viewers" | "recent" | "scarcity" | "location" | "trending";

type ProofMessage = {
  type: ProofType;
  text: string; // "{highlight}" placeholder is swapped for the highlight span
  highlight?: string;
  time?: string;
};

type HighDemandVariant = { title: string; description: string };

type UrgencyVariant = { text: string; badgeLabel: string };

type ViewersVariant = {
  countLabel: string;
  suffix: string;
  avatars: string[];
  extraCount: number;
};

type CountdownVariant = {
  label: string;
  endsAt: string; // ISO date string
  expiredLabel: string;
};

type RecentBookingToast = {
  name: string;
  location: string;
  avatar: string;
  actionLabel: string;
  timeAgo: string;
};

type PriceComparisonVariant = {
  currency: string;
  originalPrice: number;
  currentPrice: number;
  saveLabel: string;
};

type TrustSignal = { icon: LucideIcon; label: string };
type TrustStripVariant = { signals: TrustSignal[] };

type ReviewsVariant = {
  rating: number;
  count: number;
  suffixTemplate: string; // "{count}" is replaced with count.toLocaleString()
  avatars: string[];
};

type HeatVariant = {
  label: string;
  subtitle: string;
  hourlyBookings: number[];
  currentHour: number;
  tooltipTemplate: string; // "{hour}" and "{count}" placeholders
};

type Booking13Labels = {
  liveActivityLabel?: string;
  verifiedDataLabel?: string;
};

Behavior notes

  • The ticker auto-advances only when messages.length > 1: a setInterval(advance, interval) fades the current message out for 400ms, then bumps currentIndex to (prev + 1) % messages.length and fades back in. With one or zero messages no timer is set.
  • The active message index lives in internal useState and is never lifted out; there is no onChange callback, so a parent cannot observe or drive which proof message is showing. The dot buttons under the panel just set that same internal index.
  • Each message picks its icon and color from a fixed typeConfig map keyed by type; only scarcity (rose) and location (emerald) diverge from text-primary, so unlisted types would render nothing since config would be undefined.
  • renderMessage splits text on the literal token {highlight} and injects a bold colored span; if highlight is omitted the raw text is shown verbatim and the token, if present, stays as literal text.
  • The countdown is SSR-safe: remaining starts null (rendering an em-dash placeholder) and is only computed in useEffect after mount, ticking every second. It shows expiredLabel once endsAt passes, and prepends a Nd day segment only when days remain.
  • heading is injected with dangerouslySetInnerHTML, so any inline <strong> (styled bold/primary) renders as markup rather than escaped text; pass trusted strings only.
  • The heat chart normalizes each bar to max((count / max) * 100, 6)% height so empty hours still show a 6% stub, highlights the bar at currentHour in primary, and exposes each hour through both an aria-label and a Radix Tooltip built from tooltipTemplate.
  • Every optional card renders only when its variant prop is present (and trustStripVariant/heatVariant additionally require a non-empty array); passing none leaves just the live ticker panel. The whole header block (badge/heading/description) is likewise skipped when all three are absent.

More Booking blocks

View all Booking
PRO

booking25

Booking Confirmed

FREE

booking15

Booking Confirmation Receipt

PRO

booking12

Search Bar Hero

Get Pro access