LOREN HANDLED 47,231 CALLS THIS WEEKBOOKED 8,442 APPOINTMENTSGENERATED $2.1M IN PIPELINEAVG. RESPONSE TIME 0.8sSERVING 12 LANGUAGESLOREN HANDLED 47,231 CALLS THIS WEEKBOOKED 8,442 APPOINTMENTSGENERATED $2.1M IN PIPELINEAVG. RESPONSE TIME 0.8sSERVING 12 LANGUAGES

Video Testimonials & Reviews Integration

Bring credibility to your brand by displaying powerful social proof—customer testimonials, video feedback and Google Reviews—directly on your Loren AI-powered website. Build trust instantly with real experiences from real people.

Video testimonial screenshot
Part 1

Video Testimonials Feature

1. Feature Definition & Functionality

What it is: A video carousel component that displays client testimonials in video format with interactive controls.

Key Functionalities:

Video Playback

Users can play/pause videos directly in the carousel

Audio Control

Individual mute/unmute button for each video

Navigation

Left/right arrows and dot indicators to browse through testimonials

Auto-pause

When switching slides, any playing video automatically pauses

Visual Feedback

Hover effects, duration badges, rating stars

Single Video Playback

Only one video can play at a time

Responsive Design: Adapts to mobile, tablet, and desktop screens

2. How It's Created/Integrated (End-to-End Flow)

1

Data Structure Setup

Define the testimonial object structure:

interface VideoTestimonial {
  id: string;
  clientName: string;
  projectType: string;
  location: string;
  videoUrl: string;
  thumbnail: string;
  duration: string;
  rating: number;
}
2

Video Storage

Videos are stored in Supabase Storage (cloud storage service)

https://[project-id].supabase.co/storage/v1/object/public/videos/[filename].mp4

3

Component State Management

Key state variables used:

  • api: Carousel controller (for navigation)
  • current: Index of currently visible slide
  • playingVideo: ID of currently playing video (null if none)
  • mutedVideos: Set of video IDs that are muted
  • videoRefs: References to actual video HTML elements
4

Core Functions

handlePlayPause(videoId)

→ Checks if video is currently playing. If playing: pause it. If not playing: pause all other videos, then play this one.

toggleMute(videoId)

→ Toggles muted state for specific video. Updates video element's muted property.

Slide Change

→ When carousel slides change, pause any currently playing video and reset playingVideo state to null.

5

UI Components Used

  • Carousel (from shadcn/ui): Handles sliding/navigation
  • Lucide Icons: Play, Pause, Volume2, VolumeX icons
  • HTML5 Video: Native video player with custom controls
6

Integration into Main Page

// In KMJLanding.tsx (main landing page)
import VideoTestimonials from "./VideoTestimonials";

// Render in page:
<VideoTestimonials />

3. How it will look when created

The video testimonials carousel displays client testimonials with interactive controls:

Video carousel with play/pause controls
Individual mute/unmute buttons for each video
Navigation arrows and dot indicators
Rating stars and duration badges
Auto-pause when switching slides - only one video plays at a time
Part 2

Google Reviews Integration

1. Feature Definition & Functionality

What it is: A live integration with Google Places API that fetches and displays real Google reviews from the business's Google My Business profile.

Key Functionalities:

Live Data

Pulls actual reviews directly from Google

Aggregate Stats

Shows overall rating and total review count

Review Display

Shows individual reviews with reviewer name, photo, rating, text, and time posted

Error Handling

Displays appropriate messages if reviews can't be loaded

Loading State

Shows skeleton loaders while fetching data

2. How It's Created/Integrated (End-to-End Flow)

1

API Key Setup

Google Maps API Key is stored in the hook

const GOOGLE_MAPS_API_KEY = 'Fdskdhjksdskdjskdksd';
// This key enables access to Google Places API
2

Place ID Configuration

In KMJLanding.tsx

const KMJ_PLACE_ID = "ChIJP8pNs-e72YgjhjjhjxzUo";
// This unique ID identifies KMJ Construction's 
// Google Business Profile
3

Custom Hook (useGoogleReviews)

Data Flow:

Component calls hook with Place ID
Hook initializes Google Maps API Loader
Loads Google Places library
Creates PlacesService instance
Requests place details with fields: reviews, rating, user_ratings_total
Google API returns data
Hook processes and stores: reviews array, placeData, loading state, error state
Component receives data and renders
4

Data Structures

Single Review Object:

{
  author_name: "John Doe",
  author_url: "https://google.com/profile/...",
  profile_photo_url: "https://...",
  rating: 5,
  text: "Great service! Highly recommend...",
  time: 1678901234,
  relative_time_description: "2 months ago"
}

Aggregate Data:

{
  reviews: [...],
  rating: 4.8,
  user_ratings_total: 127
}
5

API Libraries Used

  • @googlemaps/js-api-loader: Loads Google Maps JavaScript API
  • @types/google.maps: TypeScript definitions for Google Maps
6

Implementation in Component

// In KMJLanding.tsx
const {
  reviews: googleReviews,
  loading: reviewsLoading,
  error: reviewsError,
  placeData
} = useGoogleReviews(KMJ_PLACE_ID);

// Conditional rendering:
if (reviewsLoading) → Show skeleton loaders
if (reviewsError) → Show error message
if (googleReviews) → Display reviews
7

Rendering Logic

Shows first 6 reviews:

googleReviews.slice(0, 6).map((review) => 
  // Render review card with:
  // - Profile photo
  // - Name and date
  // - Star rating
  // - Review text
)

Calculate statistics:

  • Total reviews: placeData.user_ratings_total
  • Average rating: placeData.rating
  • Satisfaction rate: (reviews with 4+ stars / total) × 100

3. How it will look when created

The Google Reviews integration displays real-time reviews from your Google Business Profile with:

Overall rating and total review count
Individual review cards with profile photos
Star ratings and review text
Time posted (e.g., "2 months ago")
Responsive design for all devices