# Follow-up automatiseren met Apps Script [[TOC]] ## Waarom follow-up automatiseren Elke verkoper weet dat het geld in de follow-up zit, maar consistente opvolging is tijdrovend en gaat snel mis als je agenda vol zit. Apps Script haalt de menselijke fout eruit: het script controleert elke ochtend welke deals opvolging nodig hebben en stuurt de mail voordat je je koffie op hebt. Het grote voordeel van Apps Script boven een extern automatiseringstool is dat alles binnen Google Workspace blijft. Geen losse API-sleutels, geen extra abonnementen en geen data buiten je beveiligde omgeving. :::info Apps Script vereist basiskennis van JavaScript. Heb je nog nooit code geschreven, lees dan eerst rustig de stappen door en pas het script aan op je eigen kolommen voordat je een trigger activeert. ::: ## De script-omgeving openen :::howto title="Apps Script openen vanuit Sheets" 1. Open je Sheets-CRM. 2. Ga naar **Extensies > Apps Script**. 3. De script-editor opent in een nieuw tabblad. 4. Verwijder de standaard `myFunction()`-code. 5. Je bent klaar om te schrijven. ::: ## Het basis follow-up script Dit script controleert het tabblad **Deals** op rijen waarbij de `next_action_datum` vandaag of eerder is en de deal nog niet gesloten is. Het stuurt een herinneringsmail naar de deal-eigenaar. ```javascript function stuurFollowUpHerinneringen() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var dealsSheet = ss.getSheetByName('Deals'); var data = dealsSheet.getDataRange().getValues(); var vandaag = new Date(); vandaag.setHours(0, 0, 0, 0); for (var i = 1; i < data.length; i++) { var rij = data[i]; var dealNaam = rij[2]; var fase = rij[4]; var nextActionDatum = new Date(rij[10]); var nextAction = rij[9]; var owner = rij[7]; if (!dealNaam || fase === 'Gewonnen' || fase === 'Verloren') continue; if (isNaN(nextActionDatum.getTime())) continue; nextActionDatum.setHours(0, 0, 0, 0); if (nextActionDatum <= vandaag) { var onderwerp = 'Follow-up herinnering: ' + dealNaam; var bericht = 'Hallo, ' + 'Je hebt een openstaande follow-up voor deal: ' + dealNaam + ' ' + 'Actie: ' + nextAction + ' ' + 'Geplande datum: ' + nextActionDatum.toLocaleDateString('nl-NL') + ' ' + 'Open het CRM: ' + ss.getUrl(); GmailApp.sendEmail(owner, onderwerp, bericht); } } } ``` Pas de kolomindices aan op basis van je eigen CRM-structuur. Let op dat de index bij nul begint: `rij[2]` is kolom C, `rij[4]` is kolom E, enzovoort. ## Dagelijkse trigger instellen Een script dat je handmatig moet starten helpt weinig. Stel een tijdgestuurde trigger in zodat het script elke ochtend vanzelf draait. :::howto title="Dagelijkse trigger aanmaken" 1. Klik in de Apps Script-editor op het klokpictogram links (**Triggers**). 2. Klik op **Trigger toevoegen** rechtsonder. 3. Kies bij functie: `stuurFollowUpHerinneringen`. 4. Kies als gebeurtenisbron: **Tijdgestuurd**. 5. Kies als triggertype: **Dagelijkse timer**. 6. Stel de tijd in op **8:00 tot 9:00** zodat de mails vroeg in de ochtend aankomen. 7. Klik op **Opslaan** en autoriseer de gevraagde rechten. ::: ## CRM automatisch bijwerken Breid het script uit om ook de kolom `laatste_update` bij te werken. Voeg deze regel toe direct na het versturen van de mail (vervang `12` door het kolomnummer van `laatste_update`): ```javascript dealsSheet.getRange(i + 1, 12).setValue(new Date()); ``` ## Agenda-afspraken automatisch aanmaken Geef je Apps Script ook Calendar-toegang, dan kun je per follow-up een afspraakblok in de agenda zetten: ```javascript var calendar = CalendarApp.getDefaultCalendar(); var startTijd = new Date(nextActionDatum); startTijd.setHours(9, 0, 0); var eindTijd = new Date(startTijd); eindTijd.setHours(9, 30, 0); calendar.createEvent('Follow-up: ' + dealNaam, startTijd, eindTijd, { description: nextAction, guests: owner }); ``` Dit maakt een afspraak van een half uur aan op de follow-updatum, met de deal-eigenaar als genodigde. ## Foutafhandeling en logging Een script dat stilletjes stopt bij de eerste fout is gevaarlijk: één verkeerd e-mailadres kan de hele batch blokkeren. Zet de verzendregel daarom in een `try/catch`-blok en log wat er gebeurt: ```javascript try { GmailApp.sendEmail(owner, onderwerp, bericht); console.log('Mail verstuurd voor deal: ' + dealNaam + ' naar ' + owner); } catch (e) { console.error('Mislukt voor deal ' + dealNaam + ': ' + e.message); } ``` Bekijk de logs via **Uitvoering > Uitvoeringslogboek** in de Apps Script-editor. Bij een fout zie je het regelnummer en de foutmelding. :::tip title="Test eerst handmatig" Klik in de editor op **Uitvoeren** en controleer of je de juiste mails ontvangt voordat je de automatische trigger activeert. Wil je weten hoeveel mails je vandaag nog kwijt kunt, gebruik dan `MailApp.getRemainingDailyQuota()`; die geeft het resterende aantal ontvangers terug. ::: :::warn title="Let op je dagelijkse verzendlimiet" Apps Script kent een vast aantal e-mailontvangers per dag. Verstuur je per ongeluk naar veel rijen, dan kan het script halverwege stoppen door een quotafout. Controleer hieronder de limiet voor jouw accounttype. ::: :::faq ### Hoeveel e-mails mag Apps Script per dag versturen? Een Google Workspace-account mag via Apps Script maximaal 1500 e-mailontvangers per dag aanschrijven. Gratis Gmail-accounts (consumer) zijn beperkt tot 100 ontvangers per dag. Deze limieten staan op de officiele Apps Script-quotapagina van Google en gelden per gebruiker per 24 uur. ### Hoe controleer ik mijn resterende quota in code? Gebruik `MailApp.getRemainingDailyQuota()`. Die geeft het aantal ontvangers terug dat je vandaag nog mag aanschrijven. Bouw eventueel een controle in die stopt zodra de quota bijna op is, zodat het script de volgende dag verdergaat. ### Kan het script ook WhatsApp-berichten sturen? Niet rechtstreeks. Je kunt een webhook van een WhatsApp-API-provider aanroepen met `UrlFetchApp`, maar dat vereist een extern abonnement. De eenvoudigste opties binnen Workspace blijven e-mail of een bericht in Google Chat. ### Hoe stop ik de automatische mails tijdelijk? Verwijder of pauzeer de trigger via het klokpictogram (**Triggers**) in de Apps Script-editor. De code zelf hoef je niet aan te raken; zonder actieve trigger draait het script niet meer vanzelf. ### Wat als het e-mailadres van een deal-eigenaar niet klopt? Zet de `GmailApp.sendEmail()`-aanroep in een `try/catch`-blok, zoals in het voorbeeld bij foutafhandeling. Zo blokkeert een fout bij een enkele rij niet de verwerking van alle andere deals. ### Waarom krijgt niemand een mail terwijl het script foutloos draait? Controleer of je kolomindices kloppen met je eigen tabblad en of de datums in `next_action_datum` als echte datum staan en niet als tekst. Een datum die Sheets als tekst opslaat, mislukt bij `new Date()` en wordt door de `isNaN`-controle overgeslagen. :::