Zero to AI — Episode 3: Automated Lead Generation

The Changeable Contact Engine – How we turned a simple Google Form into a lead-qualifying, call-booking, autopilot machine.

NB – Scroll down to the second half of the content to access the step-by-step instructions and code to build this for yourself. 

Hey friends — welcome back to Zero to AI, where we unpack how everyday people and small teams use AI and automation to work smarter, not harder.

Today's story comes straight out of my own consultancy, Changeable.
It's about something we quietly built that completely changed how we handle new enquiries.

We call it the Changeable Contact Engine — and it's basically our digital receptionist.

You'll ship a simple pipeline that captures leads via Google Forms, stores them in Sheets, scores them with an AI prompt, and sends a helpful, on‑brand email automatically. Start tiny, keep it safe, and iterate weekly.

Why this matters (and why now)

Quality lead generation isn't about getting more enquiries — it's about getting the right ones and moving them forward fast. When someone reaches out, the experience they get in the first minute sets the tone for everything that follows. Automation lets you deliver that gold-standard first impression every single time: instant, relevant, and human.

With a lightweight, well-designed flow, you can:

  • Attract and qualify better leads — focus your time where there's real fit, urgency, and value.
  • Deliver superior customer experiences — lightning-fast replies that feel personal, not robotic.
  • Reduce admin to near zero — no more inbox triage or copy-paste replies.
  • Guarantee consistent, high-quality responses — clear next steps tailored to each lead.
  • Auto-book meetings and workshops — qualified contacts jump straight to a calendar link, confirmations and invites handled for you.
  • Keep momentum — every action logged, visible, and measurable so nothing slips.

Do this well and your "contact us" page stops being a dead end — it becomes a reliable engine that turns curiosity into conversations, and conversations into booked time with the people who need you most.

Here's the short version:

Someone fills in a form on our website, and within seconds they either get a warm, helpful email or a booking link for a 30-minute chat. No inbox triage. No endless back-and-forth. Just clarity — for them and for us.

Let me break down why we built it, how it works, and what it's done for the business. You'll ship a simple pipeline that captures leads via Google Forms, stores them in Sheets, scores them with an AI prompt, and sends a helpful, on‑brand email automatically. Start tiny, keep it safe, and iterate weekly.

You'll learn:

  • How to design a short, high‑signal form (no friction).
  • How to route submissions into a structured Google Sheet.
  • How to score each lead (rubric + AI assist) and tag it (New / Warm / Hot).
  • How to auto‑email the right next step (resources, booking link, or discovery invite).
  • How to do this safely (NZ Privacy Act 2020 basics, audits, and logging).

Why we built it — in plain English

Leads don't wait. If someone's reaching out for help and you make them wait two days for a reply, they've already moved on.

Back in the early days, I was doing it all manually: copying form submissions into a spreadsheet, trying to work out who was a good fit, and typing custom replies one by one.

And here's what happens when you do that — you lose the hot leads, and you burn time on the cold ones.

So, we built a lightweight contact engine that does it for us —
and it's surprisingly simple:

  • It captures enquiries through a Google Form.
  • Scores each one instantly — based on fit, urgency, and value.
  • Sends the right email on autopilot.
  • Routes the qualified ones to a Calendly booking.
  • When the Calendly booking is confirmed, a Google virtual meeting is created along with the entry in Google calendar, automatically sending the invite to the contact.
  • Logs everything in a tidy Sheet for visibility.
  • And keeps running quietly in the background thanks to two tiny Google Apps Scripts.

It's fast, human, and ruthlessly practical — my three favourite words. All I experience is a notification from Google when the meeting is confirmed.

The Flow — What Actually Happens

Here's how it all plays out behind the scenes.

Step 1 — someone fills out our contact form on the Changeable website.
That form sends their details straight into a Google Sheet — we call it contact_raw.

Step 2 — a script cleans and scores that data.
It tidies up names and phone numbers, then scores three things: Fit, Urgency, and Value.
Those roll up into a total score and a "Band" — basically how ready they are:
Advanced, Operational, Emerging, or Early.

Step 3 — based on that score, it automatically sends the right reply.
If someone's a great fit, they get a warm, personal email with a Calendly booking link for a 30-minute intro call.
If they're not quite ready, they get a friendly nurture email with some helpful resources and an open invite to reply when they're ready.

Step 4 — when someone books through Calendly, a webhook triggers another script.
That logs the booking, avoids duplicates, and syncs everything back into our main contact sheet.

And finally, Step 5 — the dashboard updates in real time.
I can see who's new, who's booked, and how long it took us to reply — all at a glance.

Simple. Clean. Reliable.

The Human Side of the Tech

Now, I know that sounds a bit mechanical — but here's the magic part: It still feels personal.

Every email we send reads like a real human wrote it — because we did. We just templatized our best version of "human." For example, our qualified lead email says:

Subject: Let's get you unstuck — pick a quick time.
Hey [FirstName], thanks for reaching out about [TheirChallenge]. From what you shared, it sounds like we can help you move fast. Grab a 30-minute slot here: [CalendlyLink]. If nothing fits, just reply with a couple of times that work for you — we'll make it happen.

Talk soon,
The Changeable team.

Warm, direct, zero fluff — very Changeable.

How It's All Organised

Inside Google Sheets, we keep things tidy and transparent: one sheet only with 5 tabs.

  • Contact raw: where all the raw form data lands.
  • Contact clean: the clean, scored version — our single source of truth.
  • Calendly log: a record of every booking event.
  • debug: a quiet little log that tells us if anything weird happens.
  • ops_ref: our config — all the thresholds, weights, and wording.

You can tweak scoring or email templates right there — no coding needed.

The Scoring Model (and Why It Works)

We keep it simple:
Each lead gets a score out of 15 — based on Fit, Urgency, and Value.

Those numbers map to bands like this:

  • Advanced: Roll out the red carpet.
  • Operational: Strong fit, ready to help.
  • Emerging: Good potential, needs a bit of nurture.
  • Early: Friendly chat, but not a priority right now.

The beautiful part? All of it lives in one sheet — easy to adjust anytime.

The Scripts (Without the Geek Speak)

There are just three small scripts running this whole thing:

  1. The scorer — triggers when a form is submitted.
    It cleans data, scores it, writes the action taken, and sends the right email.
  2. The webhook listener — waits for Calendly updates.
    It logs bookings and cancellations, keeps everything deduped, and even pulls in extra info from Calendly's API.
  3. The sync job — runs hourly to make sure contact info and booking details are fully in sync.

That's it. No fancy infrastructure, no paid platform. Just pure Google magic.

Reliability, Privacy, and Good Housekeeping

We made sure it's clean and compliant:

  • Every webhook is idempotent — so no double-logging.
  • We can audit every event — what happened, when.
  • All data stays in our Google Workspace, under our control.
  • People can update or delete their data anytime — we respect that.

And every week, we do a quick check:
Any leads without an action? Any bookings missing?
Takes five minutes, keeps everything tight.

The Impact

Since building this, the difference has been night and day.

It's fast, I mean real fast: From the contact form being completed, the system records, classifies and generates the correct email with booking calendar link, and send this, in under a second.

It provides accuracy and clarity: Every lead, every action, one clean view.

Allows the team to maintain focus: We spend time talking to the right people. Qualified leads. Not managing the admin.

It enables consistency: No more "Sorry for the delay" emails.

Human touch is at the heart of the system: Automated doesn't have to mean robotic. Our responses are humanised to the point you wouldn't know that they are generated.

We built this in a weekend. It's been running for months. And honestly — it feels like having a part-time assistant who never sleeps and never forgets.

So that's the Changeable Contact Engine.

A simple system that turns curiosity into conversations — and gives you back your time to focus on what matters most.

If you want to try building your own version, check out the content on this page. It has step by step, simple instructions, with all the code included so you just copy and paste. No coding knowledge required. It's simpler than you think — and once you ship it, you'll wonder how you ever worked without it. If you need any help or have any questions, reach out. Also, if your business needs assistance with AI workflows or automation, visit our AI agency, Changeable, at www.changeable.co.nz. Take advantage of the free discovery session

Well, that's it for today. Thanks for listening — and remember: build something small, ship it fast, and let it teach you.

That's Zero to AI.

Build the Changeable Contact Engine (Zero to AI — Ultra Simple, Click-by-Click Guide)

This is a beginner‑friendly, copy‑and‑paste walkthrough. You'll turn website enquiries into qualified, booked calls on autopilot using Google Forms + Google Sheets + Apps Script + Calendly.

You'll do four things: 1) Create a Form + Sheet, 2) Paste three small Scripts, 3) Deploy a Web App + connect Calendly, 4) (Optional) Send auto‑emails on submit.

PART 1 — Make the Form + Spreadsheet (10–15 minutes)

Goal: Create a Google Form that collects exactly what we need, then link it to a Sheet.

A) Create the Google Form (click by click)

  • Go to google.com → click Blank (big + button).
  • Title: click the title at the top and type: Changeable — Contact.
  • Settings (gear icon → General):
    • Turn off "Restrict to users in your organization" (so anyone can submit).
    • Keep "Collect email addresses" off (we'll add our own Email question).
    • Make sure "Limit to 1 response" is off.
    • Click Save.
  • Back on the form, add these questions exactly (labels matter for automation):
    • Full nameShort answer → toggle Required
    • EmailShort answer → toggle Required on → click the on the question → Response validationTextEmail → Error text: Enter a valid email.
    • CompanyShort answer → leave Optional.
    • PhoneShort answer → leave Optional.
    • TimelineMultiple choice → options: This week, This month, Exploring → Required
    • What's the main challenge right now?ParagraphRequired
      (Short prompt under description: "1–3 sentences is perfect.")
    • Anything else we should know?Paragraph → Optional.
    • ConsentCheckbox → option: I agree to the privacy notice → Required
      (Add a short description with your privacy link, e.g., "We'll use your info to respond and won't share it. You can request deletion anytime.")
  • (Nice touch) Click Settings → PresentationConfirmation message:
    Thanks — we'll reply within one business day. If it's urgent, mention that in your note. → Save.
  • Click the eye (Preview) → submit a quick test using your email (this helps create columns later). Close the preview tab.

B) Link the Form to a new Sheet

  • In the Form, click Responses.
  • Click the green Link to Sheets icon → Create a new spreadsheet.
  • Click Create. Google opens the new Sheet.

C) Prepare the spreadsheet tabs

  • You'll see a tab named Form Responses 1. Right‑click it → Rename → type contact_raw → Enter.
  • Click the + button (bottom‑left) → Add a new tab → rename to contact_clean.
  • Click + again → Add a new tab → rename to calendly_log.
  • Go to contact_clean, click cell A1, then paste this on one line:

Timestamp | Date | Week | FullName | Email | Company | Phone | Timeline | Challenge | ExtraNotes | Consent | FitScore | UrgencyScore | ValueScore | TotalScore | Band | ActionTaken | ProcessedAt | ReplyMins | WithinSLA | Cal_BookedAt | Cal_Start | Cal_URL

  • With row 1 still selected: Data → Split text to columns → Separator: Custom → type | → Split.
    (Optional: Format → Wrap to keep headers readable.)
  • Go to calendly_log, click A1, paste:

Email | InviteeName | Status | BookedAt | StartTime | EndTime | EventType | EventURL | CancellationAt | Notes | Key

  • Data → Split text to columns → Custom separator: | → Split.

That's Part 1. Keep the Sheet open.

PART 2 — Add the Apps Script (copy + paste, no coding) (10–15 minutes) — Add the Apps Script (copy + paste, no coding) (10–15 minutes)

Goal: Receive Calendly webhooks safely, log bookings, sync them to contacts.

A) Open the Script Editor

  • In your Sheet, click Extensions → Apps Script (opens in a new tab).
  • If asked, give your project a name (e.g., Contact Engine).

B) Create Code.gs

  • In Apps Script, click the + (New file) → Script.
  • Name it Code (Apps Script adds .gs for you).
  • Select all placeholder code and paste the following:

/************ CONFIG ************/
const LOG_SHEET     = 'calendly_log';
const CONTACT_SHEET = 'contact_clean';

const LOG_HEADERS = [
'Email','InviteeName','Status','BookedAt','StartTime','EndTime',
'EventType','EventURL','CancellationAt','Notes','Key'
];
/********************************/

/* Utils */
function sh(name)
function mapCols(sheet, needed)
function toIso(x)

/* Debug helpers – auto-creates a 'debug' sheet for traces */
function ensureDebug()
function dbg(what, type, peek)

/* Quick GET so opening the Web App URL shows it's alive */
function doGet()

/* ——— MAIN WEBHOOK (Calendly calls this) ——— */
function doPost(e)

/* Ensure headers exist (safe anytime) */
function ensureLogHeaders()

/* One‑time cleanup if you previously got duplicates */
function dedupeLogOnce()

/* Push latest booked event per email into contact_clean (Cal_* columns) */
function syncCalendlyToContacts()

/***** Scheduling helpers (safe) *****/
function runSyncSafe()
function installSyncTrigger()
function removeSyncTriggers()

  • Press Ctrl/Cmd + S to save.

C) Create calendly_setup.gs

  • Click + → Script → name it calendly_setup.
  • Paste this code:

/****** CONFIG: fill these two lines ****************************************/
const CALENDLY_PAT = 'PASTE_YOUR_CALENDLY_PAT_HERE';
const CALLBACK_URL = 'PASTE_YOUR_WEB_APP_EXEC_URL_HERE';
/***************************************************************************/

/* Sanity check PAT (Run: testCalendlyToken) */
function testCalendlyToken()

/* List current webhooks (Run: listCalendlyWebhooks) */
function listCalendlyWebhooks()

/* Delete all, then create one fresh webhook pointing to CALLBACK_URL (Run: resetCalendlyWebhook) */
function resetCalendlyWebhook()

  • Save.

D) (Optional) Create Simulator.gs

  • Click + → Script → name it Simulator.
  • Paste this code:

/* Simulate a Calendly booking to test end-to-end (Run: simulateCalendlyBooking) */
function simulateCalendlyBooking()

  • Save.

PART 3 — Deploy the Web App + Connect Calendly (8–12 minutes)

Goal: Give Calendly a URL to notify us when someone books/cancels.

A) Deploy the Web App

  • In Apps Script, click Deploy → New deployment.
  • Click Select type → choose Web app.
  • Description: type Webhook endpoint.
  • Execute as: Me.
  • Who has access: Anyone.
  • Click Deploy.
  • If prompted: Review permissions → choose your account → Advanced → Go to → Allow.
  • Copy the Web app URL (it ends with /exec). Keep it handy.

B) Add your Calendly details

  • In Apps Script, open gs.
  • Replace both lines with your values:

const CALENDLY_PAT = 'YOUR_CALENDLY_PERSONAL_ACCESS_TOKEN';
const CALLBACK_URL = 'PASTE_THE_/exec_WEB_APP_URL_HERE';

  • Where do I get the PAT?
    • Open CalendlyIntegrationsAPI & WebhooksPersonal Access TokensNew Token → copy the token.

C) Register the webhook

  • In Apps Script, at the top‑middle function dropdown, select resetCalendlyWebhook.
  • Click Run (▶).
  • Check Logs (left sidebar → Executions): you should see Create → HTTP 201 and state: active.

D) (Optional) Simulate a booking

  • Choose function simulateCalendlyBookingRun.
  • Go back to the Sheet: a debug tab appears (with a HIT), and calendly_log shows a new row (Status: booked).

Note: If you edit Code.gs later, redeploy: Deploy → Manage deployments → EditDeploy.

PART 4 — Sync bookings to contacts (2 minutes)

Goal: Copy each email's latest booked slot into contact_clean.

  • In Apps Script, choose function syncCalendlyToContactsRun.
    • Check the contact_clean tab: columns Cal_BookedAt, Cal_Start, Cal_URL should fill for matching Email
  • Make it automatic:
    • Choose function installSyncTriggerRun.
    • Click the clock icon (Triggers) → confirm you see Time‑driven → runSyncSafe → Every hour.

You can remove it anytime with removeSyncTriggers.

PART 5 — (Optional) Auto‑email on form submit (5 minutes)

Goal: Send the right email immediately (qualified → booking link, others → helpful resources).

A) Create Emails.gs

  • Click + → Script → name it Emails.
  • Paste this code:

/* Simple auto-reply based on TotalScore or Band from contact_raw submission */
function onFormSubmit(e)

  • Save.

B) Add the trigger

  • In Apps Script, click the clock icon (Triggers).
  • Click + Add Trigger (bottom‑right).
  • Choose which function to run: onFormSubmit.
  • Select event source: From spreadsheet.
  • Select event type: On form submit.
  • Click Save.

Tip: Keep your email copy in a hidden templates sheet if you want non‑technical edits later. Update code to read from sheet when you're ready.

PART 6 — Test the whole thing (5–10 minutes)

  • Open your Google Form and submit a test using your email.
  • In contact_clean, confirm your row exists (your own formulas can calculate TotalScore/Band).
  • If you enabled Part 5, check your inbox for the auto‑reply.
  • In Calendly, book a slot using the same email.
  • Go to the Sheet:
    • calendly_log → new row shows Status = booked.
    • Run syncCalendlyToContacts (or wait for the hourly trigger): your row gets Cal_BookedAt / Cal_Start / Cal_URL.

Done. You've built your first always‑on lead engine.

Troubleshooting (fast fixes)

  • Webhook deployed but nothing logs? Re‑check Deploy → Manage deployments. Make sure access is Anyone and you pasted the /exec URL into gs.
  • "Missing header" error: Double‑check header spelling in both tabs. Use Split text to columns with |
  • Auto‑email didn't send: Confirm you added the on form submit trigger, and your Form question labels match the keys in the code (Email, Full name, etc.).
  • Wrong contact didn't update: The booking email must exactly match the contact's Email in contact_clean.
  • Quota errors: Gmail and UrlFetch have daily quotas; test with a few entries first.

Privacy & Pause

  • Data stays in your Google Workspace. Honour delete/update requests.
  • To pause automation: in Apps Script Triggers, turn off runSyncSafe and onFormSubmit. Turn back on anytime.

You did it 🎉

You now have a calm, human, low‑maintenance lead flow: – Qualified people can book within seconds.
– The right reply goes out automatically.
– Every enquiry and booking lives in one tidy place.

If you want, I can create a starter template (Sheet + code preloaded) so you just connect your Form + Calendly and hit go.

Illustration of a man using a laptop representing AI-powered automated lead generation tools.