Summit Ridge Dental's website delivers a poor mobile experience and a mediocre desktop experience. The homepage takes 6.2 seconds to paint its largest visible element on mobile — more than double the 2.5-second threshold Google considers "good." The primary cause is a single uncompressed 3.1 MB hero image served at full resolution to all devices, compounded by three render-blocking third-party scripts that delay the browser from starting layout work. The booking page is the second-worst performer, with layout shifts caused by a late-loading appointment widget that pushes the page content down after the user has started reading.
| URL | LCP | CLS | INP | FCP | TBT | Score |
|---|---|---|---|---|---|---|
| / | 6.2s | 0.31 | 285ms | 3.8s | 1,820ms | 34 |
| /services/ | 5.4s | 0.14 | 240ms | 3.2s | 1,440ms | 41 |
| /book-appointment/ | 5.9s | 0.42 | 410ms | 3.6s | 2,100ms | 28 |
| /about/ | 4.8s | 0.04 | 210ms | 2.9s | 980ms | 47 |
| /contact/ | 4.1s | 0.18 | 230ms | 2.6s | 1,100ms | 44 |
Resource load timeline from navigation start to LCP. Green dashed line marks the 2.5s "good" threshold.
What's consuming time before LCP fires: server response (gray), render-blocking scripts (dark red), image/widget download (red).
Pattern: Render-blocking scripts account for 2.0–2.6 seconds on every page. Image download adds 1.8–3.2 seconds depending on asset weight. Server response time is acceptable (0.3–0.4s) — the problem is entirely client-side.
The homepage hero image (hero-banner.jpg) is 3.1 MB, 4032 × 3024 px, served as a JPEG with no srcset, no width/height attributes, and no lazy loading on below-fold images. The /services/ page serves a 2.4 MB team photo under identical conditions. All five tested pages serve full-resolution originals regardless of viewport width.
The hero image is the LCP element on 4 of 5 pages. At 3.1 MB on a 4G mobile connection (~1.6 Mbps effective throughput), the image alone takes approximately 15 seconds to download before the browser can paint it. This is the single largest contributor to the 6.2-second mobile LCP. Every visitor on a mobile device stares at a blank or partially loaded page for over 6 seconds before seeing the primary content.
No <img> srcset or sizes attributes are present. Images are served from the WordPress /wp-content/uploads/ directory with no CDN, no image optimization plugin, and no WebP conversion. The server sends Cache-Control: no-cache on image responses, forcing re-download on every visit.
Convert all hero and above-fold images to WebP format at 80% quality. Implement responsive srcset with breakpoints at 480w, 768w, 1200w, and 1920w. Add explicit width and height attributes to prevent layout shift. Add loading="lazy" to all below-fold images. Configure Cache-Control: public, max-age=31536000, immutable on static image assets.
Low — 2–3 hours with an image optimization plugin (ShortPixel, Imagify) or manual conversion via CLI tooling.
The HTML <head> contains synchronous <script> tags for Google Tag Manager (gtm.js), a Facebook Pixel (fbevents.js), and a live chat widget (widget.js). All three load synchronously before the browser can begin parsing the page body.
These three scripts add 1.8 seconds of Total Blocking Time on mobile. The browser cannot render any content — not even the navigation or page headline — until all three scripts have downloaded, parsed, and executed. Visitors on slower connections see a blank white screen for nearly 4 seconds.
The scripts are loaded via <script src="..."> without async or defer attributes. Google Tag Manager should be loaded asynchronously by default, but the implementation uses a legacy synchronous snippet. The Facebook Pixel and chat widget scripts have no asynchronous loading path configured.
Move Google Tag Manager to the standard async snippet. Add defer attribute to the Facebook Pixel script. Defer the chat widget script and initialize it on user interaction (scroll or click) rather than on page load. This removes all three scripts from the critical rendering path without losing functionality.
Low — 1–2 hours of script tag modification in the theme header template.
The /book-appointment/ page loads an external scheduling widget via JavaScript injection. The widget renders 680px of content approximately 2.8 seconds after initial page load, pushing all content below the fold downward. CLS measured at 0.42 on mobile — over 4x the acceptable threshold.
A patient attempting to book an appointment on mobile sees the page load, begins scrolling to read provider information, and then the entire page jumps downward when the widget loads. This is disorienting and frequently causes users to tap the wrong element. On conversion-critical pages, layout instability directly correlates with abandonment.
The widget <div> has no explicit height set. When the JavaScript loads and injects the iframe, the container expands from 0px to 680px, shifting all subsequent content. The widget script loads from a third-party CDN with no resource hint (no preconnect, no preload).
Set a fixed min-height on the widget container matching the rendered widget height (min-height: 680px). Add a preconnect hint for the widget CDN origin. Add a skeleton loading state (CSS placeholder) inside the container so the user sees a visual placeholder before the widget renders.
Low — 30 minutes to add the min-height and preconnect; 1 hour if adding a skeleton loader.
The site loads two Google Fonts families (Montserrat 400/600/700 and Open Sans 400/600) via a standard <link> tag. No font-display descriptor is set. Fonts are not preloaded. Each page load shows a flash of unstyled text (FOUT) as the system font renders, then swaps to the web font, causing a visible text re-render and minor layout shift.
The font swap adds 0.03–0.06 CLS per page (contributing to the cumulative shift) and adds approximately 400ms to FCP on mobile because the browser waits for the font file before painting styled text.
The Google Fonts <link> tag does not include &display=swap. No <link rel="preload"> or <link rel="preconnect"> tags reference the Google Fonts origin (fonts.googleapis.com, fonts.gstatic.com).
Add <link rel="preconnect" href="https://fonts.googleapis.com"> and <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> to the <head>. Append &display=swap to the Google Fonts URL. Optionally self-host the font files for full cache control.
Low — 15 minutes for preconnect and display=swap; 1 hour for self-hosting.
CSS, JavaScript, and image files return Cache-Control: no-cache, no-store or no Cache-Control header at all. Every repeat visit re-downloads all assets from the origin server.
Returning visitors receive no performance benefit from caching. A patient who visits the homepage, navigates to /services/, and then returns to the homepage re-downloads 8.7 MB of assets on the round trip. This wastes bandwidth, increases server load, and makes repeat page loads as slow as the first visit.
The GoDaddy shared hosting environment does not set cache headers on static files by default, and no .htaccess rules override this behavior.
Add cache headers via .htaccess: set Cache-Control: public, max-age=31536000, immutable for versioned assets (images, fonts, hashed CSS/JS) and Cache-Control: public, max-age=3600 for HTML pages. Implement cache-busting via query strings or filename hashing on CSS/JS updates.
Low — 30 minutes to configure .htaccess.
Ordered by estimated performance gain weighted against implementation effort. Working through this list from top to bottom yields the maximum cumulative improvement.
| # | Action | Priority | Effort |
|---|---|---|---|
| 1 | Compress and convert all images to responsive WebP with srcset Resolves the primary LCP bottleneck across all 5 pages. Expected LCP improvement: 2.5–3.0s on mobile. |
Critical | 2–3 hrs |
| 2 | Defer all third-party scripts out of the critical rendering path Removes 1.8s of Total Blocking Time. Expected FCP improvement: 1.0–1.5s. |
High | 1–2 hrs |
| 3 | Set fixed min-height on the appointment widget container Eliminates 0.42 CLS on the booking page — the highest-traffic conversion page. |
High | 30 min |
| 4 | Implement font preconnect and display:swap Reduces FCP by ~400ms and eliminates FOUT-related layout shift. |
Medium | 15 min |
| 5 | Configure static asset cache headers via .htaccess Improves repeat-visit performance by eliminating redundant 8.7 MB re-downloads. |
Medium | 30 min |
Five priority URLs were benchmarked across mobile (emulated Moto G Power on 4G) and desktop (cable connection) using Lighthouse 12.x via PageSpeed Insights. Lab testing only — no CrUX field data was available for this domain. No Google Search Console access was provided.
Server-side performance (TTFB optimization, PHP configuration, database query performance), CDN configuration, and application-layer caching (page caching, object caching) were not assessed. Third-party widget performance was observed but not tested in isolation. No A/B testing or tag manager audit was performed.
Lab scores represent controlled-environment performance and may differ from real-user experience. Lighthouse scores fluctuate between runs; values reported are the median of three consecutive runs per URL. Estimated time savings are based on Lighthouse opportunity calculations and may vary depending on implementation approach.
After implementing the performance fixes above, a Security Posture Snapshot (#2) is recommended — the GoDaddy shared hosting configuration is likely missing critical HTTP security headers. For a comprehensive baseline, the Essential Diagnostic package (#10) combines this performance review with the security assessment at a bundled rate.
If the top-priority image and script fixes yield the expected improvements, a follow-up Lighthouse benchmark in 30 days will confirm the gains and identify any remaining opportunities. The Performance Quick Wins remediation service (#17) is available if the team prefers hands-on implementation support for the fixes identified in this report.