Cursus
Handmatige gegevensinvoer is de vijand van productiviteit. Als jouw team vertrouwt op het extraheren van data uit operationele e-mails, zoals facturen, boekingsbevestigingen of klantfeedbackformulieren, dan ken je vast de nachtmerrie van traditionele parseermethoden.
Historisch gezien vertrouwden ontwikkelaars op Regular Expressions (Regex) om details te halen zoals factuurnummers of bedragen. Maar Regex is extreem kwetsbaar; zodra een leverancier zijn e-mailsjabloon wijzigt of een willekeurige regeleinde toevoegt, valt de hele parser stilletjes om.
In deze tutorial laat ik je zien hoe je met Generatieve AI een volledig geautomatiseerde, headless pijplijn bouwt die dit probleem oplost. We schrijven een lichtgewicht script dat ongelezen Gmail-berichten leest, de ongestructureerde tekst doorstuurt naar de Gemini API voor slimme extractie, en de perfect gestructureerde JSON-data rechtstreeks in een Google Sheet vastlegt.
Vereisten:
- Een Google-account
- Basiskennis van JavaScript (Google Apps Script)
- Een Gemini API-sleutel
Wat is Google Apps Script?
Google Apps Script is een cloudgebaseerd, snel ontwikkelplatform op basis van JavaScript waarmee je Google Workspace-apps zoals Google Docs, Sheets, Slides en meer kunt automatiseren, aanpassen en uitbreiden.
Omdat het platform direct op de servers van Google draait, hoef je geen software te installeren, geen lokale omgevingen te configureren en geen infrastructuur te beheren.
Apps Script geeft ontwikkelaars/low-code-ontwikkelaars de mogelijkheid om programmatisch te werken met Google Workspace-tools zoals Docs, Sheets, Slides, Drive en meer. Je kunt automatiseringen bouwen en draaien via aangepaste menu’s, knopklikken of tijdschema’s, of de service gebruiken om add-ons te bouwen en te publiceren voor de Google Workspace Marketplace.
Hoe Google Apps Script werkt
Google Apps Script neemt het zware werk van backendconfiguratie en API-authenticatie uit handen, zodat je je kunt focussen op logica en data. Dat gebeurt met verschillende functies:
- Cloud-native editor: Je schrijft, debugt en deployt je JavaScript-code volledig in een webgebaseerde IDE, direct in je browser.
- Ingebouwde services: In plaats van te worstelen met OAuth en complexe API-calls, gebruik je kant-en-klare globale objecten (zoals SpreadsheetApp, MailApp of DriveApp) om native met Google-services te werken.
- Eventgestuurde triggers: Scripts kunnen handmatig worden uitgevoerd via aangepaste menuknoppen, of automatisch worden gepland met tijdgestuurde triggers (bijv. elke middernacht) en eventgestuurde triggers (bijv. wanneer een gebruiker een Google Form indient).
De Google Apps Script-architectuur: Gmail-naar-Sheets-pijplijn
Voordat we het script schrijven, schetsen we hoe data door deze pijplijn stroomt. De architectuur steunt op vier afzonderlijke componenten die samenwerken:
- Gmail (bron): Het proces begint met het doorzoeken van je inbox met standaardzoekoperators (zoals is:unread label:invoices). Het script isoleert de juiste e-mailthreads en extraheert zowel de platte tekst van de e-mail als eventuele bijgevoegde pdf-bestanden.
- Apps Script (compute): Dit fungeert als de orkestratielaag. Het doorloopt de ongelezen threads, zet bijlagen om naar base64-data en handelt de logica af voor foutmeldingen en batchverwerking.
- Gemini API (transformatie-engine): Apps Script stuurt een multimodale payload (de e-mailtekst plus de pdf’s) naar het Gemini 2.5 Flash-model. Door een strikt JSON-responseschema mee te geven in de API-call dwingen we het model exacte waarden te extraheren zoals leverancier, totaalbedrag en valuta, in plaats van conversatietekst te genereren.
- Google Sheets (bestemming): Zodra Gemini de gestructureerde JSON retourneert, parseert Apps Script de resultaten, bundelt ze in één array en voegt de data in batches in op de eerstvolgende lege rij van je actieve spreadsheet met setValues().

Waarom Google Apps Script als compute-laag voor deze build gebruiken?
Het grootste voordeel is het volledig wegnemen van infrastructuuroverhead. Er is nul serverprovisioning nodig en je hoeft geen Docker-containers te configureren of complexe OAuth-flows op te zetten om je e-mails te lezen of naar een spreadsheet te schrijven.
Omdat Apps Script native integreert met services als GmailApp en SpreadsheetApp, handelt Google de authenticatie intern af. Jij schrijft simpelweg de code en verbindt de endpoints.
Stap 1: Bereid je Google Apps Script-omgeving voor
Voor we code schrijven, moeten we onze externe afhankelijkheden voorbereiden. Dit omvat toegang verkrijgen tot de Gemini API, onze doelsheet aanmaken en onze Gmail-inbox configureren om binnenkomende facturen correct te labelen.
De Gemini API-sleutel genereren
Voor onze slimme gegevensextractie hebben we toegang tot de Gemini API nodig.
- Navigeer naar Google AI Studio en log in met je Google-account.
- Klik in het navigatiemenu links op Get API key.
- Klik op de knop Create API key. Je kunt deze sleutel aanmaken in een bestaand Google Cloud-project of AI Studio een nieuw project voor je laten aanmaken.
- Kopieer de gegenereerde tekenreeks.
Beveiligingsbest practice: Raak deze sleutel niet kwijt, maar belangrijker nog: plan niet om hem in platte tekst in je code te hardcoden. Houd hem tijdelijk op je klembord of in een beveiligde notitie; we zullen hem in de volgende stap veilig opslaan in onze Apps Script-omgeving.

De Google Sheet voorbereiden en de sleutel beveiligen
We hebben een plek nodig om de geëxtraheerde data op te slaan. Deze sheet fungeert ook als lanceerplatform voor ons automatiseringsscript.
1. Stel de databasekoppen in Maak een nieuwe lege Google Sheet. Maak in de eerste rij de volgende kolomkoppen aan die overeenkomen met het JSON-schema dat we in ons script definiëren:
- Datum
- Leverancier
- Factuurnummer
- Totaalbedrag
- Valuta
- Itemoverzicht
- E-maillink
Vries de bovenste rij zodat de koppen zichtbaar blijven naarmate je data groeit.

2. Open Apps Script en sla de API-sleutel op Nu de Sheet bestaat, kunnen we de Apps Script-editor er rechtstreeks vanuit openen. Dit koppelt onze code automatisch aan deze specifieke spreadsheet.
- Klik in je Google Sheet op Extensies > Apps Script in het bovenste menu.

- Zodra de editor opent, kijk je in de linkerzijbalk en klik je op het tandwielpictogram om Projectinstellingen te openen.

- Scroll naar beneden naar Script Properties.
- Klik op Add script property.
- Typ onder Property exact
GEMINI_API_KEY. - Plak onder Value de API-sleutel die je eerder uit AI Studio hebt gekopieerd.
- Klik op Save script properties.

De code die we later schrijven, haalt deze waarde nu veilig op tijdens runtime zonder je inloggegevens bloot te geven.
Stap 2: Schrijf de Google Apps Script-code
Terwijl je in de Apps Script-editor bent, kun je eventuele standaardcode verwijderen. We bouwen onze automatiseringsengine blok voor blok.
1. Configuratie en UI-instelling
We beginnen met het definiëren van een globaal configuratieobject. Dit is een clean-code-best practice die alle hardgecodeerde variabelen op één plek groepeert, zodat je alleen dit bovenste blok hoeft te bewerken.
We voegen ook een onOpen()-functie toe. Deze ingebouwde Apps Script-trigger maakt automatisch een aangepast menu in je Google Sheet, zodat niet-technische gebruikers het script handmatig kunnen draaien zonder de code-editor te openen.
const CONFIG = {
searchQuery: "is:unread label:invoices",
model: "gemini-2.5-flash",
adminEmail: Session.getActiveUser().getEmail() // Automatically emails the script owner if it crashes
};
/**
* Creates a custom menu in Google Sheets so non-technical users can run the script manually.
*/
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('🤖 AI Automations')
.addItem('Fetch New Invoices', 'processInvoices')
.addToUi();
}
2. De orkestratie-setup
De functie processInvoices() fungeert als hoofdorkestrator. Hij begint met het veilig ophalen van je API-sleutel uit de Script Properties die we eerder hebben ingesteld.
Vervolgens gebruikt hij de ingebouwde GmailApp-service om je inbox te bevragen.
Door GmailApp.search(CONFIG.searchQuery) aan te roepen, haalt het script een array met e-mailthreads op die voldoen aan onze regel is:unread label:invoices.
Als er matches zijn, loopt het script door elke thread heen, pakt het laatste bericht, extraheert de platte tekst en haalt eventuele bijgevoegde pdf-bestanden eruit.
function processInvoices() {
const apiKey = PropertiesService.getScriptProperties().getProperty("GEMINI_API_KEY");
if (!apiKey) {
throw new Error("GEMINI_API_KEY is missing! Please set it in Script Properties.");
}
const threads = GmailApp.search(CONFIG.searchQuery);
if (threads.length === 0) return;
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const batchData = [];
const processedThreads = [];
3. E-mails en multimodale pdf’s verwerken
Terwijl we de e-mailthreads doorlopen, pakken we het laatste bericht. Facturen komen echter zelden als platte tekst binnen; ze zijn bijna altijd als pdf bijgevoegd.
Door gebruik te maken van Gemini 2.5 Flash, dat van nature multimodaal is, loopt ons script door latestMessage.getAttachments(), pakt alle pdf’s, zet ze om naar een Base64-tekenreeks en geeft ze direct mee aan de API-payload als inlineData.
Gemini “leest” de pdf visueel en extraheert de data net zo gemakkelijk als tekst.
for (let i = 0; i < threads.length; i++) {
const thread = threads[i];
const latestMessage = thread.getMessages().pop();
const emailBody = latestMessage.getPlainBody();
const emailDate = latestMessage.getDate();
const emailLink = https://mail.google.com/mail/u/0/#inbox/${thread.getId()};
const attachments = latestMessage.getAttachments();
try {
const geminiParts = [];
geminiParts.push({ text: "Extract invoice details from this email and any attached documents:\n\n" + emailBody });
// Add PDF attachments as base64 to the prompt
for (const attachment of attachments) {
if (attachment.getContentType() === "application/pdf") {
geminiParts.push({
inlineData: {
mimeType: "application/pdf",
data: Utilities.base64Encode(attachment.getBytes())
}
});
}
}
// Invoke Gemini API
const extractedData = callGeminiAPI(apiKey, geminiParts);
4. Batch-insertie en foutafhandeling
Om de prestaties te optimaliseren, schrijven we niet rij voor rij naar de spreadsheet.
In plaats daarvan duwen we de geëxtraheerde JSON-data in een array (batchData) en schrijven we alles in één keer weg met setValues() aan het einde.
Let op de try...catch-blok.
Als Gemini hallucinaties vertoont of faalt op een specifieke e-mail, crasht het script niet volledig. In plaats daarvan wordt de fout netjes opgevangen en gebruikt het MailApp.sendEmail() om de beheerder onmiddellijk te waarschuwen, wat zorgt voor hoge observeerbaarheid.
// Push to batch array instead of writing one-by-one
batchData.push([
emailDate,
extractedData.vendor || "Unknown Vendor",
extractedData.invoiceNumber || "N/A",
extractedData.totalAmount || 0.00,
extractedData.currency || "USD",
extractedData.itemsSummary || "N/A",
emailLink
]);
processedThreads.push(thread);
} catch (error) {
MailApp.sendEmail(CONFIG.adminEmail, "🚨 Invoice Pipeline Error", error.toString());
}
}
// Batch Write to Sheets
if (batchData.length > 0) {
const lastRow = Math.max(sheet.getLastRow(), 1);
sheet.getRange(lastRow + 1, 1, batchData.length, batchData[0].length).setValues(batchData);
}
// Mark all processed threads as read so they aren't parsed again
processedThreads.forEach(t => t.markRead());
}
Tot slot roept het script thread.markRead() aan voor elke verwerkte e-mail. Zo negeert het script de volgende keer deze e-mails en zoekt het alleen naar nieuwe.
5. De Gemini API-helperfunctie (JSON-modus)
Bij het aanroepen van LLM’s gebruiken ontwikkelaars vaak prompt engineering zoals "Return a JSON block". Modellen antwoorden echter regelmatig met converserende opvultekst (bijv. "Sure, here is your data: [JSON]"), wat ervoor zorgt dat downstreamcodeparsers crashen.
Door responseMimeType: "application/json" in te stellen en een strikt responseSchema op te geven, dwingen we de Gemini REST API om uitsluitend te antwoorden met een gegarandeerd JSON-object met precies onze spreadsheetkolomkoppen.
function callGeminiAPI(apiKey, partsArray) {
const url = https://generativelanguage.googleapis.com/v1beta/models/${CONFIG.model}:generateContent?key=${apiKey};
const responseSchema = {
type: "OBJECT",
properties: {
vendor: { type: "STRING" },
invoiceNumber: { type: "STRING" },
totalAmount: { type: "NUMBER" },
currency: { type: "STRING" },
itemsSummary: { type: "STRING" }
},
required: ["vendor", "totalAmount"]
};
const payload = {
contents: [{ parts: partsArray }],
generationConfig: {
responseMimeType: "application/json",
responseSchema: responseSchema
}
};
const options = {
method: "POST",
contentType: "application/json",
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(url, options);
const jsonResponse = JSON.parse(response.getContentText());
return JSON.parse(jsonResponse.candidates[0].content.parts[0].text);
}
Stap 3: Automatiseer je Google Apps Script-pijplijn
Code is alleen waardevol als het je leven makkelijker maakt.
Google Apps Script biedt krachtige uitvoeromgevingen, van interactieve, gebruikersgerichte knoppen tot volledig headless achtergrond-cronjobs.
Methode 1: Triggeren via de spreadsheet-UI
Als je deze tool bouwt voor een niet-technisch boekhoudteam, willen zij waarschijnlijk niet de Apps Script-codeeditor openen om de facturen van vandaag te verwerken.
Omdat we de functie onOpen() in onze code hebben opgenomen, bindt Apps Script automatisch een aangepast menu in de interface van Google Sheets telkens wanneer de spreadsheet wordt geopend.
- Ga terug naar je Google Sheet en ververs de pagina.
- Wacht een paar seconden en kijk in de bovenste menubalk. Je ziet een nieuw dropdownmenu genaamd 🤖 AI Automations.
- Klik erop en selecteer Fetch New Invoices.

- De eerste keer dat je dit uitvoert, vraagt Google je om het script te autoriseren (om je Gmail te lezen en e-mails namens jou te verzenden). Na toestemming wordt het script realtime uitgevoerd. Je ziet de geëxtraheerde JSON-data live in de rijen verschijnen!
Methode 2: Headless automatisering via tijdgestuurde triggers
Als je echte set it and forget it-automatisering wilt, kun je native tijdgestuurde triggers gebruiken om de pijplijn autonoom op de achtergrond te laten draaien.
- Klik in de Apps Script-editor op Triggers (klokpictogram) in de linkerzijbalk.

- Klik rechtsonder op Add Trigger.

- Stel de functie in op processInvoices.
- Wijzig de gebeurtenisbron naar Time-driven en stel in dat hij op een uurtimer draait (bijv. elke 6 uur).
- Klik op Save.

Je headless AI-pijplijn is nu volledig autonoom.
Zelfs als je computer volledig uitstaat, worden de servers van Google elke zes uur wakker, scannen ze je inbox, parsen ze de facturen via Gemini, loggen ze de data in Sheets en gaan ze weer slapen.
Je kunt het succes of falen van deze achtergronduitvoeringen monitoren door in de Apps Script-editor op het tabblad Executions te klikken om de logs te bekijken.
Stap 4: Het testen van de AI-gegevensextractie
Nu de code staat, moeten we testen of de extractiepijplijn werkt zoals verwacht.
We bekijken twee praktische scenario’s om te zien hoe de Gemini API met verschillende dataformaten omgaat en hoe de daadwerkelijke responses eruitzien.
Test 1: Extractie uit platte tekste-mail
Eerst testen we een factuur die rechtstreeks in de e-mailtekst is opgenomen.
- Stuur jezelf een e-mail met het onderwerp "Invoice INV-2023-88493".
- Schrijf in de body ongestructureerde tekst zoals: "Hi Team, please pay Acme Corp $450.00 USD for the Q3 software license."
- Pas het label invoices toe op de e-mail en zorg dat hij ongelezen blijft.

- Voer het script uit via het aangepaste menu.

Achter de schermen ontvangt Gemini deze ongestructureerde tekst en houdt zich strikt aan ons JSON-schema.
In plaats van te antwoorden met converserende opvultekst, retourneert het een ruwe payload.
Omdat de response perfect gestructureerde JSON is, leest onze batchData.push()-array naadloos extractedData.totalAmount en logt 6550 direct in de Google Sheet zonder complexe Regex-logica.

Test 2: Extractie uit een pdf-bijlage
Vervolgens testen we de echte kracht van Gemini 2.5 Flash door een pdf-document door te geven.
- Genereer of download een voorbeeldfactuur in pdf (bijv. voor $20.700,00 van ProTech Cloud Services).
- E-mail jezelf het pdf-document. Je kunt de e-mailbody volledig leeg laten!
- Pas het label invoices toe en markeer hem als ongelezen.

- Voer het script uit. De pijplijn detecteert de bijlage, zet deze om naar Base64 en Gemini leest het document visueel om de leverancier en het totaalbedrag te extraheren.

Hier bewijst de architectuur zijn waarde.
Je hoefde geen aangepaste OCR- (Optical Character Recognition) logica te schrijven, geen aparte pdf-parseerbibliotheek te beheren en geen reguliere expressies te schrijven om het totaalbedrag te vinden.
De LLM verwerkte de ongestructureerde visuele data native.
Conclusie
Het automatiseren van bedrijfsworkflows vereist geen zware infrastructuur of gevechten met complexe autorisatielussen.
Door Google Apps Script te koppelen aan de Gemini API hebben we een intelligente, serverloze datapijplijn gebouwd die volledig draait binnen het cloudecosysteem dat je elke dag al gebruikt.
De kracht van deze architectuur zit in de eenvoud. In plaats van servers te provisioneren, webhooks te configureren of beveiligde credentialbestanden op een externe server te beheren, verzorgt Apps Script native de context, authenticatie en uitvoering.
Ondertussen elimineert Gemini de noodzaak voor kwetsbare reguliere expressies of dure OCR-software, en transformeert het rommelige e-mailteksten en ongestructureerde pdf’s met één enkele API-call in voorspelbare databaserijen.
Wil je je vaardigheden verder uitbouwen en ontdekken wat je nog meer kunt bouwen met programmatische toegang tot LLM’s, bekijk dan DataCamps Introduction to APIs in Python of duik diep in het ontwerpen van intelligente workflows met de AI Agent Fundamentals cursus.
Ik schrijf en maak dingen op internet. Google Developer Expert voor Google Workspace, afgestudeerd in Computer Science aan NMIMS, en een gepassioneerde bouwer in automatisering en Generatieve AI.
