Create a Google Doc from a Template

A common pattern in Apps Script is to maintain a Google Doc template with named placeholders (e.g. {{CustomerName}}), then copy it and replace those placeholders with real data. This is perfect for generating contracts, proposals, or onboarding documents from a spreadsheet.

Setting Up a Template

Create a Google Doc with placeholders like:

Dear {{CustomerName}}, Thank you for choosing the {{Product}} at ${{Amount}}/month. Your account manager is {{SalesRep}} and your region is {{Region}}. Contract Date: {{Date}}

Note the Template Doc ID from its URL — you'll use it in the script.

Generating a Doc for One Customer

function createContractForCustomer() { var templateId = "YOUR_TEMPLATE_DOC_ID"; var destinationFolder = DriveApp.getFolderById("YOUR_CONTRACTS_FOLDER_ID"); // Customer data var customerName = "Sarah Johnson"; var product = "Pro Plan"; var amount = "299"; var salesRep = "Alex Martinez"; var region = "North"; var date = "2024-03-15"; // Copy the template var templateFile = DriveApp.getFileById(templateId); var newDoc = templateFile.makeCopy(customerName + " - Contract", destinationFolder); // Open and replace placeholders var doc = DocumentApp.openById(newDoc.getId()); var body = doc.getBody(); body.replaceText("{{CustomerName}}", customerName); body.replaceText("{{Product}}", product); body.replaceText("{{Amount}}", amount); body.replaceText("{{SalesRep}}", salesRep); body.replaceText("{{Region}}", region); body.replaceText("{{Date}}", date); doc.saveAndClose(); Logger.log("Contract created: " + newDoc.getUrl()); }

Bulk Contract Generation from a Sheet

This example loops over every row in the Sales Tracker sheet and generates a contract for each closed deal:

function bulkGenerateContracts() { var templateId = "YOUR_TEMPLATE_DOC_ID"; var destinationFolder = DriveApp.getFolderById("YOUR_CONTRACTS_FOLDER_ID"); var sheet = SpreadsheetApp .getActiveSpreadsheet() .getSheetByName("Sales Tracker"); var data = sheet.getRange(2, 1, sheet.getLastRow() - 1, 8).getValues(); // Columns: [Customer Name, Email, Product, Amount, Region, Sales Rep, Status, Date] data.forEach(function(row) { var customerName = row[0]; var product = row[2]; var amount = row[3].toString(); var region = row[4]; var salesRep = row[5]; var status = row[6]; var date = Utilities.formatDate(new Date(row[7]), Session.getScriptTimeZone(), "MMMM dd, yyyy"); if (status !== "Closed") return; var templateFile = DriveApp.getFileById(templateId); var newDoc = templateFile.makeCopy(customerName + " - Contract", destinationFolder); var doc = DocumentApp.openById(newDoc.getId()); var body = doc.getBody(); body.replaceText("{{CustomerName}}", customerName); body.replaceText("{{Product}}", product); body.replaceText("{{Amount}}", amount); body.replaceText("{{SalesRep}}", salesRep); body.replaceText("{{Region}}", region); body.replaceText("{{Date}}", date); doc.saveAndClose(); Logger.log("Generated contract for: " + customerName); }); }

With the sample data, contracts are generated for Sarah Johnson (Pro Plan, North) and Lisa Park (Starter Plan, South). Mark Chen is skipped because his status is In Progress.

Writing the Document URL Back to the Sheet

After generating each contract, you can write the URL back to the sheet for easy access:

// Inside the forEach loop, after doc.saveAndClose(): var urlColumn = 9; // Column I var rowIndex = data.indexOf(row) + 2; // +2 accounts for header and 0-index sheet.getRange(rowIndex, urlColumn).setValue(newDoc.getUrl());