The Problem: My Financial Tools Site Was Painfully Slow
I run ToolsForIndia.com - a collection of financial calculators (SIP, PPF, EMI, etc.) for Indian users. Simple static HTML pages. No frameworks. No fancy stuff.
But PageSpeed Insights was giving me a 35/100 score.
Initial load time: 10.2 seconds on 3G.
For users in India (where 3G is still common), this was unusable.
What Was Causing the Slowdown?
I ran Chrome DevTools Performance tab and found the culprits:
- Tailwind CDN (blocking): 4.8 seconds
- Google Analytics (blocking): 2.1 seconds
- Email capture script (blocking): 1.9 seconds
- AdSense (already async): 0.8 seconds
Total blocking time: ~9 seconds before any content rendered.
The irony? All three scripts were non-critical for initial page render.
The Fix: Defer Everything That's Not Critical
Fix #1: Defer Tailwind CSS (Biggest Impact)
Before:
<script src="https://cdn.tailwindcss.com"></script>
After:
<script defer src="https://cdn.tailwindcss.com"></script>
What defer does:
- Script downloads in parallel with HTML parsing
- Executes after HTML parsing completes
- Maintains execution order (important for dependencies)
Impact:
- Load time: 10.2s → 5.4s (saved 4.8 seconds)
- First Contentful Paint improved by 60%
Fix #2: Defer Google Analytics
Before:
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXX');
</script>
After:
<script>
window.addEventListener('load', function() {
var script = document.createElement('script');
script.async = true;
script.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXX';
document.head.appendChild(script);
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXX');
});
</script>
Why this approach:
- Analytics loads after the page fully loads
- User sees content immediately
- No impact on tracking (slight delay is acceptable)
Impact:
- Load time: 5.4s → 3.3s (saved 2.1 seconds)
Fix #3: Defer Email Capture Script
Before:
html<script async src="https://eomail5.com/form/FORM_ID.js"
data-form="FORM_ID"></script>
After:
html<script>
window.addEventListener('load', function() {
var script = document.createElement('script');
script.async = true;
script.src = 'https://eomail5.com/form/FORM_ID.js';
script.setAttribute('data-form', 'FORM_ID');
document.head.appendChild(script);
});
</script>
Impact:
- Load time: 3.3s → 2.1s (saved 1.2 seconds)
Key Lessons
-
asyncvsdefervs Manual Loading
<!-- async: Downloads in parallel, executes ASAP (may block) -->
<script async src="script.js"></script>
<!-- defer: Downloads in parallel, executes after HTML parse -->
<script defer src="script.js"></script>
<!-- Manual: Full control, loads after page ready -->
<script>
window.addEventListener('load', function() {
// Load script here
});
</script>
When to use what:
- Critical CSS/JS: Inline or normal blocking
- UI frameworks (Tailwind, Bootstrap): defer
- Analytics, ads: Manual load after page ready
- Third-party widgets: Manual load (lowest priority)
- The "Template Header" Approach
Since I have 20+ HTML pages, I don't want to update each one individually.
Solution: Create a reusable header template with all fixes:
<!-- header-template.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Deferred Tailwind -->
<script defer src="https://cdn.tailwindcss.com"></script>
<!-- Deferred Analytics -->
<script>
window.addEventListener('load', function() {
if (localStorage.getItem('analytics-consent') === 'granted') {
var script = document.createElement('script');
script.async = true;
script.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXX';
document.head.appendChild(script);
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXX');
}
});
</script>
</head>
Copy-paste this into all pages. One-time fix, massive impact.
Test on Real Devices
PageSpeed Insights is great, but test on actual 3G/4G connections.
I used Chrome DevTools:Open DevTools → Network tab
Throttling dropdown → "Slow 3G"
Hard refresh (Cmd+Shift+R)
This showed me the real user experience.
What I Learned NOT to Do
Don't defer critical CSS
I tried deferring ALL CSS initially. Result: FOUC (Flash of Unstyled Content) that looked terrible.
Rule: If CSS is needed for above-the-fold content, keep it blocking or inline it.
Don't break dependencies
Tailwind needs to load before custom Tailwind classes work. Using async instead of defer caused race conditions.
Rule: Use defer for scripts with dependencies; they execute in order.
Don't over-optimize
I tried code-splitting, tree-shaking Tailwind, etc. Not worth it for a simple site.
Rule: Fix the low-hanging fruit first. 80/20 principle.
The "Good Enough" Philosophy
Before: Chasing 100/100 PageSpeed score with complex build tools.
After: 92/100 with 3 script changes. Good enough.
My site is:
- Static HTML (no SSR, no frameworks)
- Uses CDN scripts (no build process)
- Easy to maintain (no webpack config hell)
And now it's fast.
Your Turn: Quick Audit Checklist
- Run PageSpeed Insights on your site
- Check "Reduce JavaScript execution time" section
- Identify blocking scripts:
- Analytics? → Defer after page load
- UI frameworks (Tailwind, Bootstrap)? → Add
defer - Third-party widgets? → Load last
- Test on slow connection (Chrome DevTools throttling)
- Re-run PageSpeed → Enjoy your 50+ point improvement
Code Repository
I've open-sourced the before/after versions:
Before (slow):
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.tailwindcss.com"></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXX"></script>
<script async src="https://eomail5.com/form/XXX.js"></script>
</head>
<body>
<!-- Content -->
</body>
</html>
After (fast):
<!DOCTYPE html>
<html>
<head>
<!-- Defer Tailwind -->
<script defer src="https://cdn.tailwindcss.com"></script>
<!-- Defer Analytics -->
<script>
window.addEventListener('load', function() {
var ga = document.createElement('script');
ga.async = true;
ga.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXX';
document.head.appendChild(ga);
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXX');
});
</script>
<!-- Defer Email Script -->
<script>
window.addEventListener('load', function() {
var email = document.createElement('script');
email.async = true;
email.src = 'https://eomail5.com/form/XXX.js';
email.setAttribute('data-form', 'XXX');
document.head.appendChild(email);
});
</script>
</head>
<body>
<!-- Content -->
</body>
</html>
Conclusion
You don't need:
- Webpack
- Build tools
- Framework migrations
- Complex optimizations
You just need:
- Understand defer vs async
- Defer non-critical scripts
- Test on real connections
Result: 79% faster load time with 3 changes.
Discussion
What's your biggest site speed bottleneck? Share in the comments!
Building financial tools for 1 billion Indians at ToolsForIndia.com. Follow for more performance tips and dev lessons.
Meet the Creator: Chittaranjan Gopalrao Nivargi
Founder & Creator

Top comments (0)