Back to BlogAutomation

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.

December 26, 2025
6 min read

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

  1. Create the Script: Open your Google Sheet (where contracts/forms land), go to Extensions > Apps Script.
  2. Paste the Code: Copy the whole code block above into Code.gs.
  3. Configure IDs: Replace ROOT_FOLDER_ID and TEMPLATE_FOLDER_ID with IDs from your Google Drive URLs (the string after folders/).
  4. 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

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

Automate creative asset management with Google Workspace. Organize files, control versions, and share assets with clients automatically.
Automate campaign tracking with Google Workspace. Monitor performance, track budgets, and optimize campaigns from a centralized dashboard.

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.

business automationworkflow automationGoogle Apps ScriptApps Script automationGoogle Workspace businessSMB automationtime savingsmanual task elimination