Use this page if you want the automatic version of the missed-call workflow.
The main workflow is:
Missed call → text → short form → Google Sheet → AI job note → follow-up status
The script below helps with the AI part.
When a new form response lands in your Google Sheet, the script sends the request details to AI and fills in:
AI job note
AI priority
AI next step
Callback script
This is optional.
If you want the fastest setup, use the manual AI version from the newsletter first.
Use this script when you want the AI columns to fill automatically.
What you need
Before you start, you need:
A Google Form
A Google Sheet connected to that form
The team columns added to the Sheet
An AI API key
15–30 minutes to test carefully
Step 1: Set up your form
Create a Google Form called:
Quick Service Request
Use these questions:
What do you need help with?
How urgent is it?
Where is the job?
Best time to call back?
Anything else we should know?
Connect the form responses to a Google Sheet.
Name the Sheet:
Missed Call Leads
Step 2: Add these columns to the Sheet
In the Google Sheet, add these team columns to the right side:
Status
Assigned to
Next follow-up
AI job note
AI priority
AI next step
Callback script
Outcome notes
The script needs these exact four output column names:
AI job note
AI priority
AI next step
Callback script
If you change those column names, you also need to update the script.
Step 3: Get an AI API key
This script example uses the Gemini API.
You can create an API key from Google AI Studio.
Important: free or low-cost AI API plans may have limits and different data-use rules.
Before sending customer details to any AI tool, check the provider’s data settings.
You can reduce privacy risk by sending only what the AI needs.
For example, send this:
Water heater leak, ZIP 28277, wants help today
Not this:
Full name, full address, phone number, private notes
Step 4: Open Apps Script
Open the Google Sheet connected to your form.
Go to:
Extensions → Apps Script
Delete any starter code.
Paste the full script below.
Step 5: Paste this script
/**
* FieldCue missed-call AI job note script
*
* What it does:
* - Runs when a Google Form response lands in the linked Google Sheet
* - Reads the submitted row
* - Sends service, urgency, location, and notes to Gemini
* - Writes back AI job note, priority, next step, and callback script
*
* Before using:
* - Add these output columns to your Sheet:
* AI job note
* AI priority
* AI next step
* Callback script
*
* - Add your Gemini API key in Apps Script:
* Project Settings -> Script Properties
* Property: GEMINI_API_KEY
* Value: your API key
*/
const CONFIG = {
model: "gemini-2.5-flash",
// Change these if your Google Form question names are different.
inputHeaders: {
service: "What do you need help with?",
urgency: "How urgent is it?",
location: "Where is the job?",
notes: "Anything else we should know?"
},
// These columns must exist in your Sheet.
outputHeaders: {
jobNote: "AI job note",
priority: "AI priority",
nextStep: "AI next step",
callbackScript: "Callback script"
}
};
/**
* Main function. Set this up as an installable trigger:
* Event source: From spreadsheet
* Event type: On form submit
*/
function onFormSubmit(e) {
const sheet = e.range.getSheet();
const rowNumber = e.range.getRow();
processRow_(sheet, rowNumber);
}
/**
* Optional test function.
* Use this after you submit one test form response.
* It processes the last row in the active Sheet.
*/
function testLastRow() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const rowNumber = sheet.getLastRow();
processRow_(sheet, rowNumber);
}
function processRow_(sheet, rowNumber) {
const lastColumn = sheet.getLastColumn();
const headers = sheet.getRange(1, 1, 1, lastColumn).getValues()[0];
const row = sheet.getRange(rowNumber, 1, 1, lastColumn).getValues()[0];
const values = {
service: getValueByHeader_(headers, row, CONFIG.inputHeaders.service),
urgency: getValueByHeader_(headers, row, CONFIG.inputHeaders.urgency),
location: getValueByHeader_(headers, row, CONFIG.inputHeaders.location),
notes: getValueByHeader_(headers, row, CONFIG.inputHeaders.notes)
};
const aiResult = createJobNote_(values);
writeValueByHeader_(sheet, headers, rowNumber, CONFIG.outputHeaders.jobNote, aiResult.job_note);
writeValueByHeader_(sheet, headers, rowNumber, CONFIG.outputHeaders.priority, aiResult.priority);
writeValueByHeader_(sheet, headers, rowNumber, CONFIG.outputHeaders.nextStep, aiResult.next_step);
writeValueByHeader_(sheet, headers, rowNumber, CONFIG.outputHeaders.callbackScript, aiResult.callback_script);
}
function createJobNote_(values) {
const apiKey = PropertiesService.getScriptProperties().getProperty("GEMINI_API_KEY");
if (!apiKey) {
throw new Error("Missing GEMINI_API_KEY in Script Properties.");
}
const prompt = `
Read this service request and create a short job note for a home-service business.
Return ONLY valid JSON with these keys:
{
"job_note": "",
"priority": "High | Medium | Low",
"next_step": "",
"callback_script": ""
}
Rules:
- Keep the job note practical and under 40 words.
- Do not promise pricing or availability.
- If urgency is today or emergency, priority should usually be High.
- Callback script should sound natural and short.
- Do not include full personal details unless they are necessary.
Service: ${values.service || ""}
Urgency: ${values.urgency || ""}
Location: ${values.location || ""}
Notes: ${values.notes || ""}
`;
const url = `https://generativelanguage.googleapis.com/v1beta/models/${CONFIG.model}:generateContent?key=${apiKey}`;
const payload = {
contents: [
{
parts: [
{ text: prompt }
]
}
],
generationConfig: {
temperature: 0.2,
responseMimeType: "application/json"
}
};
const response = UrlFetchApp.fetch(url, {
method: "post",
contentType: "application/json",
payload: JSON.stringify(payload),
muteHttpExceptions: true
});
const status = response.getResponseCode();
const body = response.getContentText();
if (status < 200 || status >= 300) {
throw new Error(`Gemini API error ${status}: ${body}`);
}
const parsed = JSON.parse(body);
const text = parsed.candidates &&
parsed.candidates[0] &&
parsed.candidates[0].content &&
parsed.candidates[0].content.parts &&
parsed.candidates[0].content.parts[0] &&
parsed.candidates[0].content.parts[0].text;
if (!text) {
throw new Error(`No AI text returned: ${body}`);
}
return JSON.parse(text);
}
function getValueByHeader_(headers, row, headerName) {
const index = headers.indexOf(headerName);
return index === -1 ? "" : row[index];
}
function writeValueByHeader_(sheet, headers, rowNumber, headerName, value) {
const index = headers.indexOf(headerName);
if (index === -1) {
throw new Error(`Missing output column: ${headerName}`);
}
sheet.getRange(rowNumber, index + 1).setValue(value || "");
}
Step 6: Add your API key
In Apps Script, go to:
Project Settings → Script Properties
Add a new property:
Property: GEMINI_API_KEY
Value: your Gemini API key
Save it.
Do not paste your API key directly into the Sheet.
Do not share your API key with anyone.
Step 7: Create the trigger
In Apps Script, open:
Triggers
Add a new trigger.
Use these settings:
Function to run: onFormSubmit
Deployment: Head
Event source: From spreadsheet
Event type: On form submit
Save it.
Google may ask you to authorize the script.
Review the permissions before approving.
Step 8: Test it
Submit a test form response.
Use a simple test like:
Service: Repair
Urgency: Today
Location: 28277
Notes: Water heater leaking in garage
Go back to the Sheet.
Check if these columns filled in:
AI job note
AI priority
AI next step
Callback script
If they filled in, the automation is working.
If it does not work
Check these common issues first.
The AI columns are blank
Make sure these columns exist exactly:
AI job note
AI priority
AI next step
Callback script
Column names must match the script.
The script says the API key is missing
Go back to:
Project Settings → Script Properties
Confirm this property exists:
GEMINI_API_KEY
The script cannot find your form fields
Your Google Form question names may be different.
Update this part of the script:
inputHeaders: {
service: "What do you need help with?",
urgency: "How urgent is it?",
location: "Where is the job?",
notes: "Anything else we should know?"
}
Make the text match your Sheet headers exactly.
The model name fails
The model name may change over time.
In the script, look for:
model: "gemini-2.5-flash"
If needed, replace it with the current Flash model name shown in your AI Studio account.
Privacy reminder
Use the least customer information needed.
For AI job notes, you usually do not need the customer’s full name, full address, or phone number.
A cleaner input is:
Service needed
Urgency
ZIP code
Short notes
That is usually enough to prepare a callback.
Want the simple checklist?
If you want the simple missed-call workflow checklist, reply SETUP to FieldCue Weekly and tell us what phone system, CRM, scheduling tool, or texting tool you use.
Examples:
SETUP — Google Voice
SETUP — Housecall Pro
SETUP — Just my iPhone
SETUP — Not sure
— FieldCue Weekly