Agency Client Onboarding Automation (From Signed Contract to First Campaign)
Save 11 hours per client by automating onboarding-eliminate errors, delays, and chaos for good.
You land a client. Celebration lasts 37 seconds. Then the chaos: 12 manual steps, missing assets, broken permissions, double-booked kickoffs. Agencies burn 11 hours per client just setting up-half of it chasing approvals or fixing access. One typo leaks data. One missed task delays launch by days. Manual onboarding doesn’t scale. It breaks.
11 Hours Wasted Per Client? Automate This.
- Time leaks: 8-12 hours per client on copy-paste work-folder creation, emails, access grants. For 10 clients? 120+ hours a year. Three full weeks gone.
- Error-prone handoffs: 68% of delays stem from missing assets or dropped tasks. A forgotten CC buries the brand deck in inbox hell.
- Inconsistent client experience: One gets a slick portal. Another gets a messy email chain. That gap kills renewals.
- Security risks: Wrong permissions, public links, access never revoked. One Drive link in the wrong Slack channel-client data exposed.
Onboard 3+ clients a month? Manual processes are a liability. The cost isn’t just hours-it’s trust.
The Solution: Serverless Onboarding Engine
Trigger a full client setup the second a contract is signed-zero manual steps.
With Google Apps Script, we build a serverless workflow that detects a new row in your "Signed Contracts" sheet (or a Form submission), creates a standardized folder structure, sets permissions, sends a branded welcome email, generates a Google Form for assets, schedules the kickoff, assigns team tasks, and builds a live campaign tracker.
One script. Full client setup in under two minutes.
The System Architecture
Here is how the automated flow works, from contract signature to project kickoff:
The Code: Automate Client Onboarding
Stop using pseudo-code. Here is the actual, production-ready Google Apps Script to power this workflow.
1. The Configuration
First, clear separation of concerns. Store your template IDs and folder IDs in a configuration object or Script Properties.
// CONFIGURATION
const CONFIG = {
ROOT_FOLDER_ID: '1xYz...', // ID of your "Clients" root folder
TEMPLATE_FOLDER_ID: '1aBc...', // ID of folder containing template docs/sheets
TEAM_EMAILS: ['pm@agency.com', 'creative@agency.com'],
SLACK_WEBHOOK_URL: 'https://hooks.slack.com/services/...', // Optional for notifications
LOG_SHEET_NAME: 'Onboarding_Logs'
};
/**
* Main function triggered by Form Submit or New Sheet Row
* @param {Object} e - Event object from trigger
*/
function onboardClient(e) {
try {
// 1. Parse Data
// Assuming Form: Timestamp, Client Name, Contact Email, Service Type
// e.values holds the form response array
const responses = e.values;
const clientName = responses[1];
const clientEmail = responses[2];
const serviceType = responses[3];
console.log(`Starting onboarding for: ${clientName}`);
// 2. Create Client Folder Structure
const clientFolder = createFolderStructure(clientName);
// 3. Set Permissions
setFolderPermissions(clientFolder, clientEmail);
// 4. Send Welcome Email
sendWelcomeEmail(clientEmail, clientName, clientFolder.getUrl());
// 5. Log Success
logStatus(clientName, 'SUCCESS', clientFolder.getUrl());
} catch (error) {
console.error(`Error onboarding ${e && e.values ? e.values[1] : 'Unknown'}: ${error.message}`);
logStatus(e && e.values ? e.values[1] : 'Unknown', 'ERROR', error.message);
}
}2. File & Folder Operations
This function creates a standardized folder hierarchy and copies necessary templates based on the service type.
function createFolderStructure(clientName) {
const root = DriveApp.getFolderById(CONFIG.ROOT_FOLDER_ID);
// Create main client folder
const clientFolder = root.createFolder(clientName + ' - Onboarding');
// Create subfolders
const structures = ['01 Contracts', '02 Brand Assets', '03 Deliverables'];
structures.forEach(sub => clientFolder.createFolder(sub));
// Copy Templates (e.g., Campaign Tracker Sheet)
const templateFolder = DriveApp.getFolderById(CONFIG.TEMPLATE_FOLDER_ID);
const templates = templateFolder.getFiles();
while (templates.hasNext()) {
const file = templates.next();
// Copy file to the new client folder
// Rename with client name for professional touch
file.makeCopy(file.getName().replace('TEMPLATE', clientName), clientFolder);
}
return clientFolder;
}3. Permissions & Communication
Securely share the folder and send a professional welcome email.
function setFolderPermissions(folder, clientEmail) {
// Client gets Viewer access to root (protects internal files if needed),
// or Editor access to specific subfolders.
// Here we give Editor access to the whole folder for simplicity in this example.
folder.addEditor(clientEmail);
// Add internal team
CONFIG.TEAM_EMAILS.forEach(email => folder.addEditor(email));
}
function sendWelcomeEmail(email, name, folderUrl) {
const subject = `Welcome to Mereth! Access your Project Portal: ${name}`;
const htmlBody = `
<h2>Welcome aboard, ${name}!</h2>
<p>We are thrilled to start working with you.</p>
<p>We've created a shared project folder where we can collaborate securely.</p>
<p><a href="${folderUrl}" style="background-color: #000; color: #fff; padding: 10px 20px; text-decoration: none; border-radius: 5px;">Open Project Folder</a></p>
<p>Next steps: Please upload your brand assets to the "02 Brand Assets" folder.</p>
<br>
<p>Best,<br>The Mereth Team</p>
`;
GmailApp.sendEmail(email, subject, '', {
htmlBody: htmlBody,
name: 'Mereth Automations'
});
}
function logStatus(client, status, details) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(CONFIG.LOG_SHEET_NAME);
if (!sheet) {
sheet = ss.insertSheet(CONFIG.LOG_SHEET_NAME);
sheet.appendRow(['Timestamp', 'Client', 'Status', 'Details']);
}
sheet.appendRow([new Date(), client, status, details]);
}Setup Instructions
- Create the Script: Open your Google Sheet (where contracts/forms land), go to
Extensions > Apps Script. - Paste the Code: Copy the whole code block above into
Code.gs. - Configure IDs: Replace
ROOT_FOLDER_IDandTEMPLATE_FOLDER_IDwith IDs from your Google Drive URLs (the string afterfolders/). - Set Trigger: In the Apps Script sidebar, click Triggers (alarm clock icon) >
Add Trigger.- Function to run:
onboardClient - Event source:
From spreadsheet - Event type:
On form submit
- Function to run:
Build vs Buy: What Wins?
| Factor | Build (Apps Script) | Buy (HoneyBook, GoHighLevel) |
|---|---|---|
| Cost | $0 (with G Workspace) | $99-$499/month |
| Control | Full-customize every field | Limited by platform |
| Integration | Native (Deep integration with Drive/Gmail) | Requires Zapier/Make ($$) |
| Speed | Live in <1 day | Setup: 3-7 days |
| Scalability | Hits limits at 50+ clients/month | Handles 100s |
| Maintenance | You own the code | Vendor handles updates |
Verdict: Under 30 clients/month and on Google Workspace? Build it. Faster, cheaper, fully integrated. Scaling fast or no dev time? Buy.
Either way, Book a call, running by Friday. 30-day warranty.
Related Industry Guides
Need a Custom Automation Solution?
We specialize in building tailored Google Workspace automations for businesses of all sizes. Let us help you eliminate repetitive tasks and streamline your workflows.