Case Study: A Local-SEO-Driven Clinic Website with a Real Booking Funnel
The Gupta Dental Care build, Bootstrap 5 grid, IntersectionObserver scroll reveals, a symptom-to-booking funnel, and schema.org local-business markup aimed at Kushinagar.

Building a web presence for a dental clinic is a different beast from building an app: the user is a patient, and the site's job is to convert concern into an appointment. For guptadentalcare.cyou, I designed the site as a conversion funnel, not a brochure.
Funnel Architecture
- Home, outcome-led hero, services grid, social proof (testimonials), and a persistent "Book Appointment" CTA.
- Symptom pages (
symptoms.html), content pages that target the searches patients actually type. One canonical URL per condition, each with a CTA back into booking. - Booking (
booking.html), a single-purpose conversion page: name, phone, preferred time. Minimal fields, no login, no multi-step wizard.
The principle: every page has a job to do, and the navigation hierarchy encodes that.
Bootstrap 5, Used Deliberately
The layout rides Bootstrap 5's 12-column grid with its standard breakpoints (sm 576, md 768, lg 992, xl 1200). Why a framework kit instead of a bespoke design system? Because the client's maintenance needs come first: any web developer can pick up a Bootstrap layout, and the 5.x JS bundle is dependency-free. I used the grid and the components, then overrode the theme tokens with the clinic's brand palette.
Scroll Reveals Without the JS Weight
Page animations use IntersectionObserver-driven reveals (AOS-style): elements register with a threshold and a rootMargin, and receive an opacity/translate transition on intersection. Two details matter:
const io = new IntersectionObserver(
(entries) =>
entries.forEach((e) => {
if (e.isIntersecting) {
e.target.classList.add("revealed");
io.unobserve(e.target); // fire once, then done
}
}),
{ threshold: 0.15, rootMargin: "0px 0px -10% 0px" }
);
- Once-semantics, unobserving after reveal means no re-trigger on scroll-back and no work spent on off-screen elements.
- The -10% bottom rootMargin reveals elements slightly before they hit the viewport, so nothing pops in at the last moment.
The Local-SEO Layer
This is where a clinic site actually wins or loses:
- On-page, geo-qualified keywords in title/meta; the H1 carries service + city.
- Structured data,
schema.orgLocalBusiness / Dentist JSON-LD: address, geo coordinates, opening hours, phone. That markup is what earns rich results (hours, phone) in the local pack. - NAP consistency, Name, Address, Phone in one canonical shape across the footer, the schema, and the booking page.
Core Web Vitals
- LCP, hero is a WebP with
fetchpriority="high"(or a text LCP with zero blocking requests). - CLS, every image box has a fixed aspect-ratio, so the page never reflows mid-load.
- TBT, all interactivity is under 2 KB of inline JS: no framework, no third-party runtime.
What I Learned
A clinic site is an SEO and funnel exercise wearing a design skin. The schema layer and the booking funnel do more for the client than any animation.