
Contact forms and lead capture forms fail silently. When a checkout breaks, you see it in your revenue. When a login breaks, users tell you immediately. When a contact form breaks, leads just stop appearing — and you don't know if it's a broken form, a slow week, or a seasonal dip.
Broken forms have a particularly long detection lag because the failure mode is absence rather than error. No one reports getting an error message; they just never hear back from you.
A contact form submission travels through several steps, any of which can fail:
Standard monitoring only covers step 1. Everything else is invisible without specific checks.
# Flask
@app.route('/health/forms')
def forms_health():
checks = {}
# 1. Test database write (can we store a submission?)
try:
db.execute('SELECT COUNT(*) FROM contact_submissions')
checks['submission_db'] = 'ok'
except Exception as e:
checks['submission_db'] = f'error: {str(e)}'
# 2. Test email notification queue
queue_depth = get_queue_size('notifications')
checks['notification_queue_depth'] = queue_depth
checks['notification_queue'] = 'ok' if queue_depth < 200 else 'degraded'
# 3. Test CRM webhook endpoint is reachable
try:
import requests
resp = requests.post(
os.environ['CRM_WEBHOOK_URL'],
json={'test': True, 'source': 'health-check'},
timeout=5
)
checks['crm_webhook'] = 'ok' if resp.status_code in [200, 201] else f'status: {resp.status_code}'
except Exception as e:
checks['crm_webhook'] = f'error: {str(e)}'
all_ok = all(v == 'ok' for v in [
checks.get('submission_db'),
checks.get('notification_queue'),
checks.get('crm_webhook'),
])
return jsonify({'status': 'ok' if all_ok else 'degraded', **checks}), \
200 if all_ok else 503
// Node.js
app.get('/health/forms', async (req, res) => {
const checks = {};
try {
// DB write test
await db.query('SELECT COUNT(*) FROM contact_submissions');
checks.submissionDb = 'ok';
// Email queue
const queue = new Queue('notifications', { connection });
const counts = await queue.getJobCounts('waiting');
checks.notificationQueueDepth = counts.waiting;
checks.notificationQueue = counts.waiting < 200 ? 'ok' : 'degraded';
// CRM webhook test
const crmResp = await fetch(process.env.CRM_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ test: true }),
signal: AbortSignal.timeout(5000),
});
checks.crmWebhook = crmResp.ok ? 'ok' : `status: ${crmResp.status}`;
const allOk = ['submissionDb', 'notificationQueue', 'crmWebhook']
.every(k => checks[k] === 'ok');
res.status(allOk ? 200 : 503).json({ status: allOk ? 'ok' : 'degraded', ...checks });
} catch (err) {
res.status(503).json({ status: 'error', error: err.message, ...checks });
}
});
If you use a third-party form tool — Typeform, HubSpot Forms, Formspree, Netlify Forms — the form itself is outside your direct control. What you can monitor:
The embed/script loading — If the third-party JS fails to load, your form may show as broken or invisible. Monitor that the form appears correctly by checking for the form element's presence.
The webhook/integration endpoint — Most form tools send a webhook to your server or CRM when a submission arrives. Monitor that endpoint:
# Your webhook receiver endpoint should respond to GET
curl -I https://yourdomain.com/webhooks/typeform
Submission notifications — If you receive email notifications for form submissions, a sudden gap in notifications (especially for high-traffic forms) is worth investigating.
A challenge with form monitoring: submitting a test form creates a fake lead in your CRM or inbox. Strategies to avoid this:
Use a dedicated test email — create a monitored inbox ([email protected]) that receives test submissions. Alert if this inbox goes silent for more than 24 hours.
Add a ?test=true parameter — handle this server-side to process the form without writing to your CRM or sending notifications.
Monitor the stack components separately — rather than simulating a full form submission, test each component (DB, queue, webhook endpoint) independently via your health check.
For businesses running paid search or SEO campaigns, a broken contact form translates directly to wasted ad spend. Traffic arrives, intent is high, the form fails, the lead is lost. The campaign metrics look fine (traffic, clicks, time on page) but the conversion disappears.
Monitoring your form submission health endpoint gives you a signal that's independent of conversion rate fluctuations — a 503 is a broken form regardless of traffic volume.
Domain Monitor monitors your /health/forms endpoint every minute. When your CRM webhook becomes unreachable, your notification queue backs up, or your database can't accept writes, you get an immediate alert — not a slow realisation weeks later that your lead flow has stopped. Create a free account.
Wildcard, SAN (multi-domain), and single-domain SSL certificates cover different use cases. Here's a clear comparison to help you pick the right type — and avoid paying for coverage you don't need.
Read moreDNS resolves correctly from your office but fails for users in other countries or on different ISPs. Here's why geographic DNS inconsistency happens and how to diagnose which layer is causing it.
Read moreRegistrar lock and transfer lock are often confused — and disabling the wrong one leaves your domain vulnerable. Here's a clear breakdown of what each does and when to use them.
Read moreLooking to monitor your website and domains? Join our platform and start today.