44 documents
Architecture Decision Records (ADRs)Status: Accepted📅2026-07-30⏱️3 min read

ADR-0004: One outbound CRM webhook to Apps Script / Sheets, not a hosted CRM

Validated leads have to land somewhere the owner will actually look. At current volume — a solo agency running early outreach — the options were:

ADR-0004: One outbound CRM webhook to Apps Script / Sheets, not a hosted CRM

  • Status: Accepted
  • Date: 2026-07-30 (recorded; implemented earlier)
  • Deciders: Junaid Siddiqui (owner)
  • Related: ../integrations/lead-capture.md, scripts/google-apps-script/SETUP.md, ADR-0003

Context

Validated leads have to land somewhere the owner will actually look. At current volume — a solo agency running early outreach — the options were:

  1. Hosted CRM (HubSpot, Pipedrive, and similar) — proper pipeline management, but a monthly cost, an API integration, an SDK dependency, and a vendor to migrate off later.
  2. Own database — full control, but this repo has no database, no ORM, and no reason to add either for a marketing site.
  3. Single generic outbound webhook to a Google Apps Script Web App that appends rows to a Google Sheet — zero cost, no npm dependency, no Google Cloud project, and a destination that can be swapped by changing one environment variable.
  4. Email notification — simple, but leads become unsearchable and unsortable.

The playbook's Tier 2 promises "CRM/WhatsApp Lead Integration", which argues for a delivery mechanism that can be pointed anywhere rather than one coupled to a specific vendor.

Decision

Deliver every validated lead as a single JSON POST to whatever CRM_WEBHOOK_URL names. The recommended receiver is a Google Apps Script Web App appending rows to a Google Sheet (scripts/google-apps-script/Code.gs, setup in scripts/google-apps-script/SETUP.md, deployed as Execute as Me / access Anyone, with Asia/Dubai date and time columns).

When CRM_WEBHOOK_URL is unset, leads are validated and logged server-side, so local development needs no webhook at all.

Being vendor-neutral is the point: the same mechanism can target a client's own CRM, an automation platform, or a WhatsApp relay without code changes.

Consequences

  • Positive:
    • No cost, no dependency, no vendor lock-in; the destination is one env var.
    • Google Sheets is immediately usable — sortable, shareable, filterable, no training.
    • Local dev works with nothing configured.
    • Directly reusable as a client deliverable, since client CRMs vary.
  • Trade-offs / costs:
    • No retry, queue, or dead-letter path. A webhook outage loses the lead beyond the server log. This is the sharpest edge.
    • No pipeline management: no stages, no follow-up reminders, no deduplication.
    • The Apps Script Web App URL is effectively a write credential — anyone holding it can append rows. It must stay in .env.local and host env only.
    • A Sheet will not scale as lead volume grows, and there is no second copy of the data.
    • "WhatsApp integration" is not implemented; the webhook merely could target a relay (../integrations/lead-capture.md).
  • Follow-ups:
    • Add retry with backoff, or persist failed payloads for replay.
    • Add owner notification on arrival — the success message promises a reply within an hour.
    • Revisit a hosted CRM once lead volume justifies pipeline management.
    • Stop describing WhatsApp delivery as pre-built until it is.