Site Speed Optimization: A Step-by-Step Guide
Why Speed Matters Beyond Rankings
Google has confirmed that page speed is a ranking factor. But speed also directly impacts your bottom line:
- Amazon found that every 100ms of latency cost them 1% in sales
- Walmart reported a 2% increase in conversions for every 1-second improvement
- The BBC lost 10% of users for each additional second of load time
For NYC businesses where every conversion matters, speed optimization pays for itself through improved user behavior metrics alone — before accounting for the ranking benefit.
Step 1: Measure Your Current Performance
Before optimizing, establish a baseline. Use multiple tools to get a complete picture:
PageSpeed Insights — Provides both lab data (Lighthouse) and field data (CrUX) for your pages. Focus on the field data section, which reflects real user experience.
WebPageTest — Offers granular waterfall charts showing exactly what loads, when, and how long each resource takes. Run tests from a server location near your primary audience (for NYC businesses, use the Virginia or New Jersey test locations).
Chrome DevTools Network Tab — Shows resource loading in real-time. Use the Performance panel for JavaScript execution analysis.
Google Search Console Core Web Vitals Report — Aggregated field data across your entire site, categorized as Good, Needs Improvement, or Poor.
Record these baseline metrics for your top 10 pages:
- Total page load time
- Time to First Byte (TTFB)
- Largest Contentful Paint (LCP)
- Total page weight (in MB)
- Number of HTTP requests
- Core Web Vitals scores (LCP, INP, CLS)
Step 2: Image Optimization
Images typically account for 50-80% of total page weight. Optimizing images is almost always the highest-impact change you can make.
Format Selection
- JPEG — Best for photographs. Use quality 80-85% (visually identical to 100% at 60-70% smaller file size)
- WebP — 25-35% smaller than JPEG at equivalent quality. Supported by all modern browsers
- AVIF — 50% smaller than JPEG. Browser support is growing but not universal. Use with WebP fallback
- PNG — Use only for images requiring transparency. Consider WebP with alpha channel as a smaller alternative
- SVG — Use for icons, logos, and simple graphics. Infinitely scalable with tiny file sizes
Responsive Images
Serve appropriately sized images for each device using srcset:
<img
src="hero-800.webp"
srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
width="1200"
height="600"
alt="Descriptive alt text"
loading="lazy"
>
A mobile user doesn’t need a 2400px wide hero image. Serving a 400px version saves 80%+ in file size.
Lazy Loading
Add loading="lazy" to images below the fold. This delays loading until the user scrolls near them, reducing initial page weight and improving LCP.
Exception: Don’t lazy-load the LCP image (typically your hero image). It needs to load as fast as possible. Use fetchpriority="high" on the LCP image instead.
Image CDN Services
Services like Cloudflare Images, Imgix, or Cloudinary can automate format conversion, resizing, and optimization. They serve the optimal image format based on the requesting browser’s capabilities.
Step 3: Caching Strategy
Caching stores copies of resources so they don’t need to be re-downloaded on subsequent visits. Implement caching at multiple levels:
Browser Caching
Configure HTTP cache headers on your server to tell browsers how long to keep resources:
# Static assets (CSS, JS, images) — cache for 1 year
Cache-Control: public, max-age=31536000, immutable
# HTML pages — revalidate every time
Cache-Control: no-cache
# API responses — cache for 5 minutes
Cache-Control: public, max-age=300
Use content hashing in file names (e.g., styles.a1b2c3.css) so browsers fetch the new version when content changes while caching the old version for its full duration.
Server-Side Caching
- Page caching stores fully rendered HTML pages so the server doesn’t rebuild them for each visitor
- Object caching (Redis, Memcached) stores database query results and computed values in memory
- Opcode caching (for PHP sites) stores compiled PHP bytecode so it doesn’t need to be recompiled on each request
CDN (Content Delivery Network)
A CDN distributes your content across servers worldwide and serves it from the location nearest to each user.
For NYC businesses:
- Cloudflare (free tier available) provides edge nodes throughout the Northeast
- AWS CloudFront integrates well with AWS hosting
- Fastly offers high-performance edge computing
CDN benefits beyond speed:
- DDoS protection
- Automatic HTTPS
- Edge-level caching
- Image optimization (on some providers)
Step 4: JavaScript Optimization
JavaScript is frequently the largest contributor to slow interactivity and poor INP scores.
Audit Your JavaScript
Use Chrome DevTools Coverage panel to identify unused JavaScript. It’s common for sites to load 500KB+ of JavaScript while only using 30% of it on any given page.
Loading Strategies
Defer non-critical scripts:
<script src="analytics.js" defer></script>
defer loads the script in parallel but delays execution until after HTML parsing completes.
Async for independent scripts:
<script src="chat-widget.js" async></script>
async loads and executes the script as soon as it’s available, without blocking HTML parsing. Use for scripts that don’t depend on other scripts or DOM content.
Dynamic import for route-specific code:
// Only load the gallery module when the user opens the gallery
button.addEventListener('click', async () => {
const { Gallery } = await import('./gallery.js');
new Gallery().init();
});
Third-Party Script Management
Third-party scripts (analytics, chat, ads, social embeds) are often the worst speed offenders because you can’t control their size or execution behavior.
Management strategies:
- Audit every third-party script for business value. Remove any that aren’t delivering measurable results
- Load third-party scripts after the main content is interactive
- Use
<link rel="preconnect">for third-party domains to reduce connection latency - Consider self-hosting critical third-party resources (like Google Fonts)
- Implement a loading facade for chat widgets — show a static button that loads the full widget only when clicked
Step 5: CSS Optimization
Critical CSS
Identify the CSS needed to render above-the-fold content and inline it directly in the HTML <head>. This eliminates a render-blocking network request.
Tools like Critical (npm package) can automate this extraction. The inlined CSS should be small (under 15KB) and cover only what’s visible without scrolling.
Remove Unused CSS
CSS frameworks like Bootstrap and Tailwind often include thousands of unused declarations. Tools for removing dead CSS:
- PurgeCSS — Analyzes your HTML and removes unused CSS selectors
- Tailwind’s built-in purge — Automatically removes unused utility classes in production builds
- Chrome DevTools Coverage — Identifies unused CSS in real-time
Minification
Minify all CSS in production by removing whitespace, comments, and redundant declarations. Build tools (Vite, Webpack, esbuild) handle this automatically.
Step 6: Server and Hosting Optimization
Time to First Byte (TTFB)
TTFB is the time from the user’s request to the first byte of the server’s response. Target: under 200ms.
If your TTFB is slow:
- Check server resource utilization (CPU, memory, disk I/O)
- Optimize database queries (add indexes, reduce query complexity)
- Implement application-level caching
- Upgrade hosting tier or provider
- Use a CDN to serve cached responses from edge servers
Hosting Selection
| Hosting Type | Best For | Typical TTFB |
|---|---|---|
| Shared hosting | Not recommended for business sites | 500-2000ms |
| VPS | Small-medium business sites | 200-500ms |
| Dedicated server | High-traffic sites | 100-300ms |
| Cloud (AWS, GCP) | Scalable, variable traffic | 50-200ms |
| Edge/serverless | Static or SSR sites | 20-100ms |
For most NYC businesses, cloud hosting or a modern platform (Vercel, Netlify, Cloudflare Pages) provides the best performance-to-cost ratio.
Compression
Enable Brotli compression (preferred) or Gzip as a fallback. Compression reduces text-based file sizes by 60-80%:
# Nginx configuration
brotli on;
brotli_types text/html text/css application/javascript application/json;
HTTP/2 or HTTP/3
Modern HTTP protocols allow multiplexed connections (multiple files transferred simultaneously over a single connection) and header compression. Most modern servers and CDNs support HTTP/2 by default. HTTP/3 (QUIC) is newer and faster, available through Cloudflare and other edge providers.
Step 7: Font Optimization
Web fonts are a common source of both speed issues and CLS problems.
Loading Strategy
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
unicode-range: U+0000-007F; /* Only load Latin characters if that's all you need */
}
Best Practices
- Use WOFF2 format — smallest file size with universal browser support
- Subset your fonts — if you only need Latin characters, don’t load Cyrillic, Greek, etc.
- Preload critical fonts:
<link rel="preload" href="/fonts/custom.woff2" as="font" crossorigin> - Limit font variations — each weight and style is a separate file. Use 2-3 variations maximum
- Consider system fonts for body text. Modern system font stacks look professional and load instantly
Step 8: Resource Hints
Resource hints tell the browser about resources it will need in the near future:
<!-- Preconnect to third-party domains you know you'll need -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<!-- Preload critical resources for the current page -->
<link rel="preload" href="/hero.webp" as="image">
<!-- Prefetch resources for likely next navigation -->
<link rel="prefetch" href="/about/">
<!-- DNS prefetch for domains you'll connect to later -->
<link rel="dns-prefetch" href="https://analytics.example.com">
Use preconnect sparingly (3-4 domains maximum) — each preconnection consumes bandwidth.
Step 9: Monitoring and Maintenance
Speed optimization isn’t a one-time project. New content, features, and third-party scripts can degrade performance over time.
Automated Monitoring
Set up automated speed monitoring using:
- SpeedCurve or DebugBear — Continuous synthetic monitoring with alerts
- Google Search Console — CWV field data updated regularly
- Lighthouse CI — Integrate performance testing into your deployment pipeline
Performance Budgets
Set maximum thresholds for key metrics:
- Total page weight: under 2MB
- JavaScript: under 300KB (compressed)
- Images: under 1MB per page
- HTTP requests: under 50
- LCP: under 2.5 seconds
Configure your build pipeline to fail when a new deployment exceeds these budgets.
Priority Order for Implementation
If you can’t do everything at once, prioritize based on impact:
- Image optimization (highest impact, lowest effort)
- Browser caching and CDN (high impact, moderate effort)
- JavaScript deferral (high impact, low-moderate effort)
- Critical CSS inlining (moderate impact, moderate effort)
- Font optimization (moderate impact, low effort)
- Server upgrade (high impact if TTFB is slow, moderate cost)
- Resource hints (low-moderate impact, low effort)
- CSS purging (moderate impact, moderate effort)
Each step compounds. A site that implements all eight steps will typically see a 60-80% reduction in load time compared to an unoptimized baseline.
For the broader technical SEO context, see our technical SEO complete guide. For specific Core Web Vitals guidance, we cover each metric in detail. And if you need hands-on help, our technical SEO services include comprehensive speed optimization.