← Back to BlogHow I Track Free Contact Requests Without Webhooks

How I Track Free Contact Requests Without Webhooks

Published on Sat Jul 19 2025



πŸ‘‹ Introduction

When I launched the Contact page on my portfolio site, I wanted to offer a way for visitors to connect with me β€” either for collaboration, hiring, or casual inquiries. While Calendly helped with booking slots, I needed a way to track contact form submissions β€” without paying for webhooks.

This blog shows how I implemented free tracking using:

  • βœ… Google Sheets (as a backend log)
  • βœ… Custom Netlify Functions (sendmail.js)
  • βœ… Email metadata as a fallback log

If you’re running a serverless site and want a transparent way to log messages or inquiries, this guide is for you.


🧩 Architecture Overview

My system is simple and cost-free:

[Frontend Form] --> [Netlify Function: sendmail.js] -->
β”œβ”€> Compose Email via maildata.js
β”œβ”€> Send Email using Resend (with Zoho reply-to)
β”œβ”€> Authenticate request via auth.js
└─> Log metadata into Google Sheet (logToSheet.js)

This way, even if Calendly doesn't send webhooks, I still have a record of who contacted me and why.


πŸ“„ Step 1: Email Metadata Includes Contact Purpose

In my maildata.js, I generate a custom email body using user inputs like:

const html = `
<h3>New Contact Request</h3>
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Reason:</strong> ${reason}</p>
<p>They would like to connect with you.</p>
`;

This helps me trace contact requests even if the Sheet logging fails. Every email carries the intent clearly.


πŸ“¨ Step 2: Sending the Email

The main serverless function sendmail.js:

  • Parses request body (user name, email, etc.)
  • Generates email body via maildata.js
  • Sends via Resend API using a custom subdomain sender
  • Includes a reply-to address hosted on Zoho Mail
  • Calls auth.js (Auth Serverless Function) to validate the API call
  • Logs data to Google Sheets
await resend.emails.send({
from: 'contact@mail.kaushikparui.com',
to: TO_ADDRESS,
subject: "New Contact Request",
html,
reply_to: 'kaushik@yourdomain.com', // Zoho-hosted inbox
});

This keeps communication one-way by default, while still enabling replies.


πŸ” Step 3: Authenticating Requests

Before logging anything, my Netlify function calls a local auth.js module:

if (!validateToken(headers['x-api-key'])) {
return {
statusCode: 401,
body: 'Unauthorized',
};
}

This layer prevents spam or unauthenticated write attempts to your Google Sheet.


πŸ“Š Step 4: Logging to Google Sheets

To avoid email-only logs, I used the Google Sheets API to append entries via logToSheet.js. I'm using a GCP Server Key, and the credentials are stored encrypted in Base64 inside Netlify environment variables.

Here’s the core:

await sheets.spreadsheets.values.append({
spreadsheetId,
range: `${sheetName}!A1`,
valueInputOption: "USER_ENTERED",
requestBody: {
values: [[timestamp, name, email, reason, status]],
},
});

This allows me to have a timestamped history of all contact requests.

A sample row in my sheet looks like:

[2025-07-18 23:40, John Doe, johndoe@email.com, Portfolio Feedback, βœ… Sent]


🧠 Why This Works (Even Without Calendly Webhooks)

Calendly does not support free webhooks. So I needed a way to rely only on form submissions from my website β€” not on Calendly to report back.

By embedding key data in both:

  • πŸ“§ The email (sent via Resend with Zoho reply-to)
  • πŸ“‹ The sheet (via Google Sheets API)

…I ensure I never lose track of a message.

If the Sheet fails, I still have the email. If email fails, I can catch it in error logs. It’s fail-safe without cost.


βš™οΈ Optional Improvements (I May Add Later)

  • βœ… Add status tracking (e.g., Sheet row = pending, replied, ignored)
  • πŸ” Set up daily email digest from Sheet data (using Google Apps Script)
  • πŸ”— Include Calendly meeting ID manually if applicable
  • πŸ” Secure Netlify Function with auth.js (done βœ…)


πŸš€ Final Thoughts

Not every project needs enterprise-grade infra. My site runs serverless on Netlify, uses free tools, and yet I still:

  • Track all contact form messages
  • Store visitor intent data securely
  • Stay in control of my own backend logic

If you're an indie developer, freelancer, or job-seeker β€” this setup gives you professional-grade tracking without cost.

Feel free to fork this idea, tweak it, or ask me questions on LinkedIn.

Stay sharp β€” and may your inbox be full of interesting opportunities! πŸ’Ό


Powered By :