A complete landing-page + webhook backend project for rapidcleanouts.com handyman lead capture.
- Responsive marketing landing page (
index.html+styles.css). - Client form handler with validation and webhook submit (
form.js). - Express backend with:
POST /api/leadendpoint.- Google Sheets lead storage.
- Optional Zoho CRM lead push.
- Optional Zoho SMTP notification emails.
- Image upload handling to
uploads/. - Honeypot anti-spam field + CORS + basic helmet security headers.
rapidcleanouts-landing/
├─ .env.example
├─ .gitignore
├─ README.md
├─ form.js
├─ index.html
├─ package.json
├─ server.js
├─ styles.css
└─ uploads/
└─ .gitkeep-
Install Node.js 18+.
-
Install dependencies:
npm install
-
Copy environment template:
cp .env.example .env
-
Fill in your
.envcredentials. -
Run locally:
npm start
-
Visit:
- Landing page:
http://localhost:3000/ - Health check:
http://localhost:3000/health
- Landing page:
- In Google Cloud Console, create/select a project.
- Enable Google Sheets API.
- Create a Service Account and generate a JSON key.
- In your target spreadsheet:
- Create a tab named
Leads. - Share the spreadsheet with
GOOGLE_CLIENT_EMAIL(Editor).
- Create a tab named
- Copy these values into
.env:GOOGLE_CLIENT_EMAILGOOGLE_PRIVATE_KEY(preserve newline escapes as\n)GOOGLE_SHEET_ID(from sheet URL)
If Zoho CRM credentials are set, the server will also push each lead into Zoho Leads.
- Create Zoho OAuth client credentials.
- Generate a refresh token with CRM scopes.
- Put values in
.env:ZOHO_CRM_CLIENT_IDZOHO_CRM_CLIENT_SECRETZOHO_CRM_REFRESH_TOKEN
- Optional regional settings:
ZOHO_CRM_ACCOUNTS_URLZOHO_CRM_API_DOMAIN
If not configured, Zoho CRM submission is skipped.
If SMTP + notification email are set, each lead triggers an email alert.
Required:
ZOHO_SMTP_USERZOHO_SMTP_PASSNOTIFICATION_EMAIL
Optional:
ZOHO_SMTP_HOST(default:smtp.zoho.com)ZOHO_SMTP_PORT(default:465)
Example for Ubuntu/Debian VM:
-
Install runtime:
sudo apt update sudo apt install -y nodejs npm nginx
-
Deploy app:
git clone <your-repo-url> cd rapidcleanouts-landing npm install --production cp .env.example .env # edit .env with production values
-
Run with PM2 (recommended):
sudo npm i -g pm2 pm2 start server.js --name rapidcleanouts-landing pm2 save pm2 startup
-
Configure Nginx reverse proxy (example server block):
server { listen 80; server_name rapidcleanouts.com www.rapidcleanouts.com; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
-
Enable site and reload nginx:
sudo nginx -t sudo systemctl reload nginx
-
Add TLS with Certbot (recommended for production).
If you want n8n to orchestrate automations, you can forward leads from the backend or directly from the client:
- Keep current setup and add an n8n call inside
/api/leadafter validation. - Or replace
/api/leadURL inform.jswith your n8n webhook endpoint.
Typical n8n flow:
- Webhook trigger receives lead.
- Google Sheets node appends row.
- Zoho CRM node or HTTP node creates lead.
- Email node sends internal notification.
- Honeypot field (
website) blocks common bot submissions. - Required field checks on client + server (
name,phone,photo). - CORS controls allowed origins (
CORS_ORIGIN). helmetadds baseline HTTP security headers.- Upload filter allows only images, max 10 MB.
- Name* (required)
- Phone* (required)
- Address
- Project Details
- Project Photo* (required)
- Desired Completion Timeline (ASAP, 1-2 weeks, 1 month, Flexible)