Custom Contact Form for Blogger: Part 14 — WordsByEkta🌿
Your Blogger Contact Form Is a Bottomless Box. Here Is How to Fix That.
No server, no plugin, no coding background needed. Just HTML, one free tool, and fifteen minutes.
Blogger gives you two contact options. The built-in Contact Gadget, which looks exactly like what it is — a default widget nobody bothered to style. Or you type your email on the page and hope spam bots are feeling generous that day.
There is a third option that most Blogger guides skip entirely: a custom HTML form that looks like yours, works like a real website, and sends messages directly to your inbox. That is what this post covers.
Why a plain HTML form does nothing
Blogger is a static host. It serves your content but has no backend — no server processing, no database, nothing to receive a form submission and forward it anywhere. So if you paste a contact form into a Blogger page without connecting it to something external, the message goes nowhere. The reader clicks Submit and your form quietly swallows it.
The fix: Formspree
Formspree is a free service that acts as the backend Blogger doesn't have. Your form submits to Formspree. Formspree forwards it to your Gmail. That is the entire setup.
You do not need to understand how it works. You just need a Formspree account and your form's unique ID — which is just a short string like xbjwnklo that goes into one line of the code.
Step 1 — Get your Formspree ID
- 1
Create a free account at formspree.ioNo credit card, no paid plan needed for basic use.
- 2
Create a new formClick "+ New Form". Name it something you'll recognise — like WordsByEkta Contact.
- 3
Copy your endpoint URLFormspree gives you a URL like
https://formspree.io/f/xbjwnklo. That last part —xbjwnklo— is your form ID. Copy it.
Step 2 — The form code
Paste this into a Blogger Page using HTML view. Replace YOUR_ID_HERE with your actual Formspree ID.
<div id="contact-wrap">
<!-- FORM -->
<form id="cf"
action="https://formspree.io/f/YOUR_ID_HERE"
method="POST"
class="cf-card">
<h3>Send a message</h3>
<p>I read every one.</p>
<label>Your name</label>
<input type="text" name="name" required
placeholder="Enter your name">
<label>Email</label>
<input type="email" name="_replyto" required
placeholder="email@example.com">
<label>Message</label>
<textarea name="message" rows="5" required
placeholder="What's on your mind?"></textarea>
<button type="submit">Send</button>
</form>
<!-- SUCCESS STATE -->
<div id="cf-thanks" style="display:none">
<h2>Sent.</h2>
<p>Taking you back to the homepage in 4 seconds.</p>
</div>
</div>
<style>
.cf-card {
max-width: 480px;
margin: 24px auto;
padding: 28px;
background: #fff;
border-radius: 14px;
box-shadow: 0 8px 24px rgba(0,0,0,.08);
border-top: 4px solid #18181b;
font-family: sans-serif;
}
.cf-card h3 { margin-top: 0; color: #18181b; }
.cf-card p { color: #71717a; font-size: 14px; }
.cf-card label {
display: block;
font-weight: 600;
font-size: 13px;
color: #3f3f46;
margin: 14px 0 5px;
}
.cf-card input,
.cf-card textarea {
width: 100%;
padding: 10px 12px;
border: 1.5px solid #e4e4e7;
border-radius: 8px;
font-size: 14px;
box-sizing: border-box;
transition: border-color .2s;
}
.cf-card input:focus,
.cf-card textarea:focus {
border-color: #18181b;
outline: none;
}
.cf-card button {
margin-top: 18px;
width: 100%;
padding: 12px;
background: #18181b;
color: #fff;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: background .2s;
}
.cf-card button:hover { background: #3f3f46; }
#cf-thanks {
max-width: 480px;
margin: 24px auto;
padding: 40px 28px;
text-align: center;
background: #fff;
border-radius: 14px;
box-shadow: 0 8px 24px rgba(0,0,0,.08);
border-top: 4px solid #22c55e;
}
#cf-thanks h2 { color: #18181b; margin-bottom: 8px; }
#cf-thanks p { color: #71717a; font-size: 14px; }
</style>
<script>
const form = document.getElementById('cf');
const thanks = document.getElementById('cf-thanks');
form.onsubmit = async (e) => {
e.preventDefault();
const res = await fetch(form.action, {
method: 'POST',
body: new FormData(form),
headers: { 'Accept': 'application/json' }
});
if (res.ok) {
form.style.display = 'none';
thanks.style.display = 'block';
setTimeout(() => window.location.href = '/', 4000);
} else {
alert('Something went wrong. Please try again.');
}
};
</script>
What each part does
| Part | What it does |
|---|---|
action="https://formspree.io/f/YOUR_ID" | Tells the form where to send submissions. This is where your Formspree ID goes. |
name="_replyto" | Tells Formspree to set the sender's email as the reply-to address. So you can reply directly from Gmail. |
e.preventDefault() | Stops the browser's default form behaviour — which would reload the page and lose everything. |
res.ok | Checks whether Formspree accepted the submission before showing the success message. |
window.location.href = '/' | Sends the reader back to your homepage after 4 seconds. The / works on any Blogger blog without needing a full URL. |
Three things worth knowing
What you built
- A contact form that matches your blog's design, not Blogger's default widget
- Messages forwarded directly to Gmail via Formspree — nothing gets lost
- A success state that confirms submission without a separate Thank You page
- Auto-redirect back to homepage after 4 seconds
- Reply-to set automatically so you can respond directly from your inbox
Everything I Learned — So You Don't Have To Figure It Out Alone
The technical mistakes I made in year one — the full HTML inside Blogger, the missing meta descriptions, the duplicate H1 tags, the links closing articles — I have written all of it down. Every fix. Every discovery. Every hour of confused trial and error turned into a clear guide.
🌿 The WordsByEkta Blogger Technical Series
- Blogger is Underrated & I'm Rooting for It: Part 1
- How to Set Up Your Blogger About Me Page: Part 2
- Google Search Console for Bloggers: Part 3
- How to Request Indexing in GSC: Part 4
- Internal Linking for Fast Indexing: Part 5
- Why Isn't My Blog Indexing?: Part 6
- Canonical Tag Fix for Blogger: Part 7
- The AdSense Locked Widget Hack: Part 8
- Use Pingomatic for Faster Indexing: Part 9
- Decoding GSC Reports: Part 10
- Get Traffic from Bing and Yahoo: Part 11
- The AdSense Checklist: Part 12
- Auto Submit Blogger Posts to Bing: Part 13
- Custom Contact Form for Blogger: Part 14 (You are here)
- Extract Blog Post URLs from Sitemap: Part 15
- Open Links in New Tab Blogger: Part 16
- Blogger HTML Mode SEO Mistakes: Part 17
- Google Takeout Blogger Not Working: Part 18
- Google Indexing API for Blogger Using Python OAuth2: Part 19
- Is Blogger Worth It Nowadays?: Part 20
- Blogger Mobile HTML Editor Trick for Full Code Copy: Part 21
- Claim Blogger Site on Pinterest (No Custom Domain): Part 22
- Follow.it Email Subscriptions Setup on Blogger: Part 23
- How to Exclude Your Own Visits from GA4 Analytics: Part 24
- Auto Update All Blogger Posts Using Python and Blogger API: Part 25
- My Blog Passed 118/118 AdSense Checks: Part 26
- Ad Networks for Blogger Besides AdSense: Part 27
Comments
Post a Comment