Scroll to Top
Published on September 26, 2025 Updated on September 26, 2025

Open a new Google...

Author Avatar
Ashish Dwivedi
Editorial Team

Google Apps Script: Build Dynamic Web Forms and Save Data to Google Sheets

  • Open a new Google Sheet. Go to the Extensions menu and click on Apps Script.
  • Paste the code we provided, but replace the spreadsheet ID with your own spreadsheet ID.
  • Deploy the Apps Script code and obtain the URL of the web form

Apps Scripts Blog

Read Blog

Apps Scripts Code

// =====================




// ==== Code.gs ====

// Your Spreadsheet ID (keep for saveForm / webapp if needed)
const SPREADSHEET_ID = '16vxtYxLb9052SGX6ZB5ySqh89MuheyGD-wWsS5l0r14';

/**
 * Add custom menu when spreadsheet is opened
 */
function onOpen(e) {
  const ui = SpreadsheetApp.getUi();
  ui.createMenu('Custom Tools')
    .addItem('Show Sidebar', 'showSidebar')
    .addToUi();
}

/**
 * Show the sidebar with sheet buttons
 */
function showSidebar() {
  const html = HtmlService.createHtmlOutputFromFile('Sidebar')
    .setTitle('Open Sheets');
  SpreadsheetApp.getUi().showSidebar(html);
}

/**
 * Called from sidebar: activate (or create) a sheet by name
 */
function openSheetByName(sheetName) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = ss.getSheetByName(sheetName);

  if (!sheet) {
    sheet = ss.insertSheet(sheetName);
  }

  ss.setActiveSheet(sheet);
  return `Opened sheet: ${sheetName}`;
}

/**
 * Existing doGet for forms
 */
function doGet(e) {
  let form = e.parameter.form || 'signup';
  return HtmlService.createHtmlOutputFromFile(form)
    .setTitle('Web Form - ' + form)
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
    .addMetaTag('viewport', 'width=device-width, initial-scale=1');
}

/**
 * Existing saveForm function
 */
function saveForm(formName, formData) {
  try {
    const ss = SpreadsheetApp.openById(SPREADSHEET_ID);
    let sheet = ss.getSheetByName(formName);

    if (!sheet) {
      sheet = ss.insertSheet(formName);
      const headers = ['Timestamp', ...Object.keys(formData)];
      sheet.getRange(1, 1, 1, headers.length).setValues([headers]);
    } else {
      const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
      const newHeaders = Object.keys(formData).filter(k => !headers.includes(k));

      if (newHeaders.length) {
        sheet.getRange(1, headers.length + 1, 1, newHeaders.length).setValues([newHeaders]);
      }
    }

    const allHeaders = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
    const rowData = [new Date()];

    for (let i = 1; i < allHeaders.length; i++) {
      const h = allHeaders[i];
      rowData.push(formData[h] || '');
    }

    sheet.appendRow(rowData);
    return { status: 'success', message: 'Data saved successfully' };

  } catch (err) {
    Logger.log(err);
    return { status: 'error', message: err.message };
  }
}








 

Sidebar Sheet Launcher Template

<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  <style>
    /* Global Styles */
    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      margin: 0;
      padding: 0;
      background: linear-gradient(135deg, #74ebd5, #9face6);
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    /* Container Card */
    .container {
      background: #fff;
      padding: 30px 40px;
      border-radius: 15px;
      box-shadow: 0 8px 20px rgba(0,0,0,0.15);
      max-width: 350px;
      width: 100%;
      text-align: center;
      animation: fadeIn 0.7s ease-in-out;
    }

    /* Heading */
    h2 {
      margin-bottom: 20px;
      color: #333;
      font-size: 24px;
      letter-spacing: 1px;
    }

    /* Buttons */
    button {
      width: 100%;
      padding: 12px;
      margin: 10px 0;
      font-size: 16px;
      font-weight: bold;
      background: linear-gradient(135deg, #4285f4, #3367d6);
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
      transition: all 0.3s ease;
      box-shadow: 0 4px 10px rgba(0,0,0,0.2);
    }

    button:hover {
      background: linear-gradient(135deg, #3367d6, #274b9f);
      transform: translateY(-2px);
      box-shadow: 0 6px 14px rgba(0,0,0,0.3);
    }

    button:active {
      transform: translateY(0);
      box-shadow: 0 3px 7px rgba(0,0,0,0.2);
    }

    /* Status Message */
    #status {
      margin-top: 18px;
      font-size: 14px;
      font-weight: 500;
      color: #28a745;
      padding: 8px;
      border-radius: 5px;
      background: #e6f9ee;
      display: none;
    }

    /* Animation */
    @keyframes fadeIn {
      from { opacity: 0; transform: translateY(20px); }
      to { opacity: 1; transform: translateY(0); }
    }
  </style>
</head>
<body>
  <div class="container">
    <h2>📊 Open Sheets</h2>
    <button onclick="openSheet('Basics')">Basics</button>
    <button onclick="openSheet('Dribble')">Dribble</button>
    <button onclick="openSheet('Signup')">Signup</button>
    <div id="status"></div>
  </div>

  <script>
    function openSheet(name) {
      google.script.run
        .withSuccessHandler(msg => {
          const status = document.getElementById('status');
          status.style.display = 'block';
          status.innerText = msg;
        })
        .openSheetByName(name);
    }
  </script>
</body>
</html>

Animated Sign Up Form Template

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Animated Sign Up Form</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    /* All your CSS styles here */
    /* (The full CSS code goes here from your original HTML) */
  </style>
</head>
<body>

  <!-- Animated blur circles -->
  <div class="blur-circle circle-1"></div>
  <div class="blur-circle circle-2"></div>
  <div class="blur-circle circle-3"></div>
  <div class="blur-circle circle-4"></div>

  <div class="container">
    <div class="blur-background">
      <div class="header">
        <h1><i class="fas fa-user-plus"></i> Sign up</h1>
        <p>Complete your registration in a few simple steps</p>
      </div>

      <form id="signupForm">
        <div class="form-container">

          <!-- Basic Details Section -->
          <div class="form-section">
            <h2 class="section-title"><i class="fas fa-user"></i> Basic Details</h2>
            <div class="form-group">
              <label for="fullName">Full Name</label>
              <input type="text" id="fullName" class="form-control" placeholder="Enter Full Name" required>
            </div>
            <div class="form-group">
              <label for="dob">Date of Birth</label>
              <input type="text" id="dob" class="form-control" placeholder="MM/DD/YYYY" required>
            </div>
          </div>

          <!-- Consistency Section -->
          <div class="form-section">
            <h2 class="section-title"><i class="fas fa-signature"></i> Consistency</h2>
            <div class="form-group">
              <label for="nameSignature">Name (Signature)</label>
              <input type="text" id="nameSignature" class="form-control" placeholder="Your Signature">
            </div>
            <div class="form-group">
              <label for="workParty">Select Party You Work For</label>
              <select id="workParty" class="form-control">
                <option value="">Select Party...</option>
                <option value="party1">Party A</option>
                <option value="party2">Party B</option>
                <option value="party3">Party C</option>
              </select>
            </div>
          </div>

          <!-- Education Section -->
          <div class="form-section">
            <h2 class="section-title"><i class="fas fa-graduation-cap"></i> Education</h2>
            <div class="form-group">
              <label for="degree">Degree</label>
              <input type="text" id="degree" class="form-control" placeholder="Latin Degree">
            </div>
            <div class="form-group">
              <label for="campusUniversity">Campus University</label>
              <input type="text" id="campusUniversity" class="form-control" placeholder="College name appears here">
            </div>
            <div class="form-group">
              <label for="gradYear">Graduate Year</label>
              <select id="gradYear" class="form-control">
                <option value="1999">1999</option>
                <option value="2000">2000</option>
                <option value="2001">2001</option>
                <option value="2002">2002</option>
                <option value="2003">2003</option>
              </select>
            </div>
          </div>

          <!-- Additional Details Section -->
          <div class="form-section">
            <h2 class="section-title"><i class="fas fa-address-card"></i> Additional Details</h2>
            <div class="form-group">
              <label for="majesty1">MAJESTY</label>
              <input type="text" id="majesty1" class="form-control" placeholder="Words & Names">
            </div>
            <div class="form-group">
              <label for="majesty2">MAJESTY</label>
              <input type="text" id="majesty2" class="form-control" placeholder="Career">
            </div>
            <div class="form-group">
              <label for="contact">User Contact</label>
              <input type="text" id="contact" class="form-control" placeholder="Phone or Email">
            </div>
          </div>

        </div>

        <button type="submit" class="btn">Submit Form <i class="fas fa-arrow-right"></i></button>
      </form>

      <div class="footer">
        <p>© 2023 Elegant Forms. All rights reserved.</p>
      </div>
    </div>
  </div>

  <script>
    // JavaScript validation + notification code
    // (Place the full JS code from your original here)
  </script>

</body>
</html>

CreativeFuse HelpDesk Template

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CreativeFuse HelpDesk</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    /* All your CSS styles here */
    /* (The full CSS code goes here from your original HelpDesk HTML) */
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>creativefuse</h1>
      <p>Hey there! Is it safe to assume you're in need of some help?<br>
      Well, no worries—we've got your back! Let's get started on<br>
      your HelpDesk Ticket by filling out the info below.</p>
    </div>

    <div class="form-container">
      <div class="progress-container">
        <div class="zigzag-track">
          <div class="circle">OUTRIGHT</div>
          <div class="circle">SYSTEM</div>
          <div class="circle">OUTRIGHT</div>
          <div class="circle">SYSTEM</div>
        </div>
        <div class="outright-text">OUTRIGHT SYSTEM</div>
      </div>

      <div class="form-card">
        <h2 class="form-title">Human Basics</h2>
        
        <form id="basicsForm">
          <div class="form-grid">
            <div class="input-group">
              <label for="fullName">Full Name</label>
              <input type="text" id="fullName" name="Full Name" placeholder="Enter your full name" required>
            </div>
            
            <div class="input-group">
              <label for="tracebackFile">Traceback File</label>
              <input type="file" id="tracebackFile" name="Traceback File">
            </div>
            
            <div class="input-group">
              <label for="company">Company</label>
              <input type="text" id="company" name="Company" value="TradeView" readonly>
            </div>
            
            <div class="input-group">
              <label for="email">Email</label>
              <input type="email" id="email" name="Email" placeholder="File for Telephone Update Your...">
            </div>
          </div>
          
          <div class="input-group">
            <label for="request">Request / Next</label>
            <textarea id="request" name="Request" placeholder="Something's created correct updates Add New functionality something else!"></textarea>
          </div>
          
          <div class="input-group">
            <label for="urgency">Urgency</label>
            <select id="urgency" name="Urgency">
              <option>Low</option>
              <option selected>Normal</option>
              <option>High</option>
              <option>Critical</option>
            </select>
          </div>
          
          <div class="notification">
            <i class="fas fa-info-circle"></i> Urgency updated successfully!
          </div>
          
          <div class="button-group">
            <button type="button" class="btn btn-back">Back</button>
            <button type="submit" class="btn btn-next">Submit</button>
          </div>
        </form>
      </div>
    </div>
  </div>

  <script>
    // Submit handler
    document.getElementById('basicsForm').addEventListener('submit', function(e) {
      e.preventDefault();

      const formData = Object.fromEntries(new FormData(this).entries());

      google.script.run
        .withSuccessHandler(() => alert("Form submitted successfully!"))
        .withFailureHandler(() => alert("Error submitting form!"))
        .saveForm("Basics", formData);
    });

    // Back button handler
    document.querySelector('.btn-back').addEventListener('click', function() {
      alert('Going back to previous step.');
    });
  </script>
</body>
</html>

Dribbble-Style Signup Form

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dribbble-Style Signup Form</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        /* ==== CSS Styles ==== */
        * {margin:0;padding:0;box-sizing:border-box;font-family:'Segoe UI',Tahoma,Geneva,Verdana,sans-serif;}
        body {background:linear-gradient(135deg,#124170 0%,#26667F 100%);min-height:100vh;display:flex;justify-content:center;align-items:center;padding:20px;}
        .background-shapes {position:fixed;top:0;left:0;width:100%;height:100%;z-index:-1;overflow:hidden;}
        .shape {position:absolute;border-radius:50%;opacity:0.3;}
        .shape-1 {width:300px;height:300px;background:#67C090;top:-100px;left:-100px;filter:blur(40px);}
        .shape-2 {width:500px;height:500px;background:#DDF4E7;bottom:-200px;right:-200px;filter:blur(50px);}
        .shape-3 {width:200px;height:200px;background:#26667F;top:50%;left:70%;filter:blur(30px);}
        .container {width:100%;max-width:450px;}
        .card {background:rgba(255,255,255,0.15);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-radius:20px;padding:40px;box-shadow:0 10px 30px rgba(0,0,0,0.2);border:1px solid rgba(255,255,255,0.1);}
        .logo {text-align:center;margin-bottom:30px;}
        .logo h1 {color:#DDF4E7;font-weight:700;font-size:32px;letter-spacing:1px;}
        .logo p {color:rgba(221,244,231,0.8);margin-top:10px;font-size:16px;}
        .form-group {margin-bottom:20px;}
        .form-group label {display:block;color:#DDF4E7;margin-bottom:8px;font-weight:500;font-size:14px;}
        .input-with-icon {position:relative;}
        .input-with-icon i {position:absolute;left:15px;top:50%;transform:translateY(-50%);color:#67C090;}
        .input-with-icon input {padding-left:45px;}
        .form-control {width:100%;padding:14px;background:rgba(255,255,255,0.1);border:1px solid rgba(255,255,255,0.2);border-radius:10px;color:#fff;font-size:16px;transition:all 0.3s ease;}
        .form-control:focus {outline:none;border-color:#67C090;box-shadow:0 0 0 2px rgba(103,192,144,0.3);}
        .form-control::placeholder {color:rgba(255,255,255,0.5);}
        .checkbox-container {display:flex;align-items:center;margin:25px 0;}
        .checkbox-container input {margin-right:10px;width:18px;height:18px;accent-color:#67C090;}
        .checkbox-container label {color:#DDF4E7;font-size:14px;}
        .checkbox-container a {color:#67C090;text-decoration:none;}
        .checkbox-container a:hover {text-decoration:underline;}
        .btn {width:100%;padding:14px;background:#67C090;color:#fff;border:none;border-radius:10px;font-size:16px;font-weight:600;cursor:pointer;transition:all 0.3s ease;}
        .btn:hover {background:#5ab083;transform:translateY(-2px);box-shadow:0 5px 15px rgba(0,0,0,0.2);}
        .signin-link {text-align:center;margin-top:30px;color:#DDF4E7;font-size:15px;}
        .signin-link a {color:#67C090;text-decoration:none;font-weight:600;}
        .signin-link a:hover {text-decoration:underline;}
        .password-toggle {position:absolute;right:15px;top:50%;transform:translateY(-50%);cursor:pointer;color:#67C090;}
        @media (max-width:576px){.card{padding:30px 20px}.logo h1{font-size:28px}.logo p{font-size:14px}}
        .error {color:#ff6b6b;font-size:13px;margin-top:5px;display:none;}
        .form-control.invalid {border-color:#ff6b6b;}
    </style>
</head>
<body>
    <div class="background-shapes">
        <div class="shape shape-1"></div>
        <div class="shape shape-2"></div>
        <div class="shape shape-3"></div>
    </div>

    <div class="container">
        <div class="card">
            <div class="logo">
                <h1>Welcome to Dribbble</h1>
                <p>Come on and create an account</p>
            </div>

            <form id="signup-form">
                <div class="form-group">
                    <label for="fullname">Full name:</label>
                    <div class="input-with-icon">
                        <i class="fas fa-user"></i>
                        <input type="text" id="fullname" class="form-control" placeholder="Full naame">
                    </div>
                    <div class="error" id="fullname-error">Please enter your full name</div>
                </div>

                <div class="form-group">
                    <label for="username">Username:</label>
                    <div class="input-with-icon">
                        <i class="fas fa-at"></i>
                        <input type="text" id="username" class="form-control" placeholder="Username">
                    </div>
                    <div class="error" id="username-error">Please choose a username</div>
                </div>

                <div class="form-group">
                    <label for="email">Email:</label>
                    <div class="input-with-icon">
                        <i class="fas fa-envelope"></i>
                        <input type="email" id="email" class="form-control" placeholder="unique@gmail.com">
                    </div>
                    <div class="error" id="email-error">Please enter a valid email address</div>
                </div>

                <div class="form-group">
                    <label for="password">Password:</label>
                    <div class="input-with-icon">
                        <i class="fas fa-lock"></i>
                        <input type="password" id="password" class="form-control" placeholder="**********">
                        <span class="password-toggle" id="password-toggle"><i class="fas fa-eye"></i></span>
                    </div>
                    <div class="error" id="password-error">Password must be at least 8 characters</div>
                </div>

                <div class="form-group">
                    <label for="confirm-password">Confirm password:</label>
                    <div class="input-with-icon">
                        <i class="fas fa-lock"></i>
                        <input type="password" id="confirm-password" class="form-control" placeholder="**********">
                        <span class="password-toggle" id="confirm-password-toggle"><i class="fas fa-eye"></i></span>
                    </div>
                    <div class="error" id="confirm-password-error">Passwords do not match</div>
                </div>

                <div class="checkbox-container">
                    <input type="checkbox" id="terms">
                    <label for="terms">I agree with the website's <a href="#">terms and conditions</a>.</label>
                </div>
                <div class="error" id="terms-error">You must agree to the terms and conditions</div>

                <button type="submit" class="btn">Sign up</button>

                <div class="signin-link">Already a member? <a href="#">Sign in</a></div>
            </form>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded',function(){
            const form=document.getElementById('signup-form');
            const passwordInput=document.getElementById('password');
            const confirmPasswordInput=document.getElementById('confirm-password');
            const passwordToggle=document.getElementById('password-toggle');
            const confirmPasswordToggle=document.getElementById('confirm-password-toggle');
            function setupPasswordToggle(toggleElement,inputElement){
                toggleElement.addEventListener('click',function(){
                    const type=inputElement.getAttribute('type')==='password'?'text':'password';
                    inputElement.setAttribute('type',type);
                    const eyeIcon=toggleElement.querySelector('i');
                    eyeIcon.classList.toggle('fa-eye');
                    eyeIcon.classList.toggle('fa-eye-slash');
                });
            }
            setupPasswordToggle(passwordToggle,passwordInput);
            setupPasswordToggle(confirmPasswordToggle,confirmPasswordInput);
            form.addEventListener('submit',function(e){
                e.preventDefault();let isValid=true;
                const fullName=document.getElementById('fullname');
                if(!fullName.value.trim()){showError(fullName,'fullname-error');isValid=false;} else{hideError(fullName,'fullname-error');}
                const username=document.getElementById('username');
                if(!username.value.trim()){showError(username,'username-error');isValid=false;} else{hideError(username,'username-error');}
                const email=document.getElementById('email');const emailRegex=/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
                if(!email.value.trim()||!emailRegex.test(email.value)){showError(email,'email-error');isValid=false;} else{hideError(email,'email-error');}
                if(passwordInput.value.length<8){showError(passwordInput,'password-error');isValid=false;} else{hideError(passwordInput,'password-error');}
                if(confirmPasswordInput.value!==passwordInput.value){showError(confirmPasswordInput,'confirm-password-error');isValid=false;} else{hideError(confirmPasswordInput,'confirm-password-error');}
                const terms=document.getElementById('terms');
                if(!terms.checked){document.getElementById('terms-error').style.display='block';isValid=false;} else{document.getElementById('terms-error').style.display='none';}
                if(isValid){alert('Form submitted successfully!');form.reset();}
            });
            function showError(inputElement,errorElementId){inputElement.classList.add('invalid');document.getElementById(errorElementId).style.display='block';}
            function hideError(inputElement,errorElementId){inputElement.classList.remove('invalid');document.getElementById(errorElementId).style.display='none';}
            confirmPasswordInput.addEventListener('input',function(){if(confirmPasswordInput.value!==passwordInput.value){showError(confirmPasswordInput,'confirm-password-error');} else{hideError(confirmPasswordInput,'confirm-password-error');}});
        });
    </script>
</body>
</html>