Most African SMEs take 2โ€“3 days to fully onboard a new client. Document collection goes back and forth on WhatsApp. The contract lives in a Word file on someone's desktop. The ID gets checked manually โ€” or not at all. By the time everything is signed, the client's enthusiasm has cooled.

This guide shows you exactly how to compress that entire process into under 24 hours โ€” using tools you already have: WhatsApp, Google Sheets, and Google Apps Script. No paid software. No technical degree required.

What you'll build: A WhatsApp bot that collects client details, validates their SA ID, auto-generates a contract, sends it for signature, and notifies you when it's complete โ€” all while you sleep.

Why most onboarding processes are broken

Here's the typical flow for a professional services business in South Africa:

  1. Client messages on WhatsApp
  2. You reply manually (often hours later)
  3. You ask them to email documents
  4. They email some, forget others
  5. You follow up 2โ€“3 times
  6. You manually copy their ID number into a spreadsheet
  7. You create a contract in Word, attach their details
  8. You send the PDF via email
  9. You wait for a signature
  10. You file everything manually

That's 10 steps, most of which require your personal attention. If you're onboarding 10 clients a month, that's a part-time job just in admin.

The problem isn't that you're slow โ€” it's that the process has no automation built into it. Every step requires a human decision. We're going to change that.

The 5-step automated onboarding flow

Here's what your new flow will look like after you follow this guide:

1
Client messages your WhatsApp number
A bot responds instantly โ€” day or night โ€” and begins collecting their details through a structured 5-question conversation.
2
Bot collects intake information
Name, company, email, SA ID number, service needed โ€” collected one question at a time. Answers are automatically logged to a Google Sheet.
3
SA ID is validated automatically
The system validates the 13-digit ID number using the Luhn algorithm โ€” checking the date of birth, gender, citizenship status, and check digit. Invalid IDs trigger an automatic re-request.
4
Contract generated and sent
A Google Doc template is populated with the client's details, converted to PDF, stored in Drive, and the download link is sent to the client on WhatsApp. They reply "I AGREE" to sign.
5
Welcome message + your notification
Client gets a personalised welcome with next steps. You get a WhatsApp notification that a new client has been fully onboarded โ€” with a link to their record in Sheets.

โœ“ Average time from first message to signed contract using this system: under 4 hours. Compared to the industry average of 2โ€“3 days.

What you need to build this

Note on WhatsApp Business API: The free WhatsApp Business App cannot run automated flows. You need API access. 360dialog is the most affordable SA-friendly option. Meta (Facebook) also offers direct access but requires more setup.

Step 1: Set up your Google Sheet

Create a new Google Sheet with the following columns. This is your client database โ€” every onboarding will log here automatically.

Column A: Timestamp Column B: WhatsApp Number Column C: Full Name Column D: Company Name Column E: Email Address Column F: SA ID Number (restricted access โ€” see POPIA note below) Column G: Service Requested Column H: Status (INTAKE / VERIFIED / CONTRACT_SENT / ONBOARDED) Column I: Contract URL Column J: Owner Notified (Yes/No)

POPIA note: Restrict access to Column F (SA ID numbers) to yourself only. In Google Sheets, right-click the column header โ†’ "Protect range" โ†’ add only your email as an editor. SA ID numbers are personal information under POPIA and must be stored with appropriate access controls.

Step 2: Create your contract template in Google Docs

Take your existing contract and create a Google Doc version. Replace the client-specific fields with placeholders in double curly braces:

This agreement is entered into between {{BUSINESS_NAME}} ("Service Provider") and {{CLIENT_NAME}} ("Client"), ID number {{CLIENT_ID}}, on {{DATE_TODAY}}. Email: {{CLIENT_EMAIL}} Service requested: {{SERVICE_TYPE}} ...

Note the Google Doc ID from its URL โ€” you'll need it in the next step. The URL looks like: docs.google.com/document/d/DOCUMENT_ID_HERE/edit

Step 3: Write the Apps Script

In your Google Sheet, go to Extensions โ†’ Apps Script. This is where the automation lives. Here's the core logic for the ID validation function โ€” the most technically interesting part:

// SA ID Luhn validation function validateSAID(idNumber) { if (!/^\d{13}$/.test(idNumber)) return false; // Extract date of birth const year = parseInt(idNumber.substring(0, 2)); const month = parseInt(idNumber.substring(2, 4)); const day = parseInt(idNumber.substring(4, 6)); if (month < 1 || month > 12) return false; if (day < 1 || day > 31) return false; // Luhn algorithm check let sum = 0; for (let i = 0; i < 12; i++) { let digit = parseInt(idNumber[i]); if (i % 2 !== 0) { digit *= 2; if (digit > 9) digit -= 9; } sum += digit; } const checkDigit = (10 - (sum % 10)) % 10; return checkDigit === parseInt(idNumber[12]); }

This function checks that the ID number has the right format, a valid date of birth, and passes the Luhn checksum โ€” the same algorithm used by South African banks to verify ID numbers.

Step 4: Handle the WhatsApp conversation flow

Your WhatsApp API will send a webhook to your Apps Script whenever a message arrives. Here's the state machine โ€” the logic that decides what question to ask next based on where the client is in the flow:

function handleIncomingMessage(phoneNumber, messageText) { const sheet = SpreadsheetApp.getActiveSheet(); const row = findOrCreateClientRow(phoneNumber); const status = sheet.getRange(row, 8).getValue(); // Column H: Status if (status === '' || status === 'NEW') { // First message โ€” start intake sendWhatsApp(phoneNumber, "Hi! ๐Ÿ‘‹ I'm the NanoLeap assistant. Let's get you set up.\n\n" + "First, what's your full name?" ); sheet.getRange(row, 8).setValue('ASKED_NAME'); } else if (status === 'ASKED_NAME') { sheet.getRange(row, 3).setValue(messageText); // Column C: Name sendWhatsApp(phoneNumber, `Thanks ${messageText}! What's your company name?`); sheet.getRange(row, 8).setValue('ASKED_COMPANY'); } else if (status === 'ASKED_COMPANY') { sheet.getRange(row, 4).setValue(messageText); // Column D: Company sendWhatsApp(phoneNumber, "What's your email address?"); sheet.getRange(row, 8).setValue('ASKED_EMAIL'); } else if (status === 'ASKED_EMAIL') { sheet.getRange(row, 5).setValue(messageText); // Column E: Email sendWhatsApp(phoneNumber, "And your SA ID number? (13 digits)"); sheet.getRange(row, 8).setValue('ASKED_ID'); } else if (status === 'ASKED_ID') { if (validateSAID(messageText)) { sheet.getRange(row, 6).setValue(messageText); // Column F: ID sheet.getRange(row, 8).setValue('VERIFIED'); generateAndSendContract(row, phoneNumber); } else { sendWhatsApp(phoneNumber, "That ID number doesn't look right. Please check and try again."); } } }

Step 5: Auto-generate and send the contract

When the ID is verified, the system automatically creates a personalised contract PDF:

function generateAndSendContract(row, phoneNumber) { const sheet = SpreadsheetApp.getActiveSheet(); const clientName = sheet.getRange(row, 3).getValue(); const companyName = sheet.getRange(row, 4).getValue(); const clientId = sheet.getRange(row, 6).getValue(); const clientEmail = sheet.getRange(row, 5).getValue(); const templateId = 'YOUR_GOOGLE_DOC_TEMPLATE_ID_HERE'; const templateDoc = DriveApp.getFileById(templateId); const newDoc = templateDoc.makeCopy(`Contract - ${clientName}`); // Replace placeholders const doc = DocumentApp.openById(newDoc.getId()); const body = doc.getBody(); body.replaceText('{{CLIENT_NAME}}', clientName); body.replaceText('{{BUSINESS_NAME}}', companyName); body.replaceText('{{CLIENT_ID}}', clientId); body.replaceText('{{DATE_TODAY}}', new Date().toLocaleDateString('en-ZA')); doc.saveAndClose(); // Convert to PDF and store link const pdfBlob = DriveApp.getFileById(newDoc.getId()).getAs('application/pdf'); const pdfFile = DriveApp.createFile(pdfBlob); const pdfUrl = pdfFile.getUrl(); sheet.getRange(row, 9).setValue(pdfUrl); // Column I: Contract URL sheet.getRange(row, 8).setValue('CONTRACT_SENT'); // Send to client sendWhatsApp(phoneNumber, `Hi ${clientName}! Your service agreement is ready:\n\n` + `๐Ÿ“„ ${pdfUrl}\n\n` + `Please review and reply *I AGREE* to confirm your signature and complete your onboarding.` ); }

Common issues and how to fix them

Client doesn't respond to intake questions

Set up a stall detection function that fires after 2 hours, 24 hours, and 72 hours of inactivity. Each follow-up message should be warmer and more personal. After 72 hours with no response, notify the owner to follow up personally.

ID validation fails for a valid ID

Common causes: spaces in the 13-digit number, a dash included, or a typo. The bot should strip spaces and dashes automatically before validating. You can also add a fallback: after 2 failed attempts, send the client your direct contact to complete manually.

Contract template not filling correctly

Make sure your placeholder text matches exactly โ€” including the double curly braces and the exact same capitalisation as in your code. Google Docs replaceText is case-sensitive.

What this system can't do (yet)

This guide covers the foundation. A full production system also needs:

Want us to build this for you?

The full production system โ€” with all the edge cases handled, POPIA-compliant, tested and live in 5 days. You only pay after delivery.

Book a Free Audit โ†’

The bottom line

Client onboarding is the first impression your business makes. A 3-day manual process tells clients that your operations are slow. A 24-hour automated process tells them you're professional, efficient, and ready to deliver.

The good news: you don't need expensive software to do this. WhatsApp Business API, Google Sheets, and Apps Script are either free or nearly free. The investment is in the setup โ€” and this guide gives you the foundation.

If you want the full production version without the setup time, book a free audit. We'll tell you exactly what we'd build for your specific business and what it would cost. You pay nothing until it's live and working.