One useful application of the Google Docs API is to merge information from one or more data sources into a document.
This page outlines how you can take data from an external source and insert it into an existing template document.
A template is a special type of document containing the same fixed text for all documents created from the template, along with designated placeholders where other dynamic text can be placed. For example, a contract template might have fixed content, along with spots for the receiver's name, address, and other details. Your app can then merge customer-specific data into the template to create finished documents.
There are several reasons why this approach is useful:
-
It's easy for designers to fine-tune a document's design using the Google Docs editor. This is much easier than tuning parameters in your app to set the rendered layout.
-
Separating content from presentation is a well-known design principle with many benefits.
A basic recipe
Here's an example of how you can use the Docs API to merge data into a document:
-
Create your document using placeholder content to help you with the design and format. Any text formatting you want to replace is preserved.
-
For each element you'll be inserting, replace the placeholder content with a tag. Be sure to use strings that are unlikely to occur normally. For example,
{{account-holder-name}}might be a good tag. -
In your code, use the Google Drive API to make a copy of the document.
-
In your code, use the Docs API's
batchUpdate()method with the document name and include aReplaceAllTextRequest.
Document IDs reference a document and they can be derived from the URL
https://docs.google.com/document/d/ documentId /edit
Example
Consider the following example, which replaces 2 fields across all tabs of a template with real values to generate a finished document.

To perform this merge, you can use the code below.
Java
String customerName = "Alice" ; DateTimeFormatter formatter = DateTimeFormatter . ofPattern ( "yyyy/MM/dd" ); String date = formatter . format ( LocalDate . now ()); List<Request> requests = new ArrayList <> (); // One option for replacing all text is to specify all tab IDs. requests . add ( new Request () . setReplaceAllText ( new ReplaceAllTextRequest () . setContainsText ( new SubstringMatchCriteria () . setText ( "{{customer-name}}" ) . setMatchCase ( true )) . setReplaceText ( customerName ) . setTabsCriteria ( new TabsCriteria () . addTabIds ( TAB_ID_1 ) . addTabIds ( TAB_ID_2 ) . addTabIds ( TAB_ID_3 )))); // Another option is to omit TabsCriteria if you are replacing across all tabs. requests . add ( new Request () . setReplaceAllText ( new ReplaceAllTextRequest () . setContainsText ( new SubstringMatchCriteria () . setText ( "{{date}}" ) . setMatchCase ( true )) . setReplaceText ( date ))); BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest (); service . documents (). batchUpdate ( documentId , body . setRequests ( requests )). execute ();
Node.js
let customerName = 'Alice' ; let date = yyyymmdd () let requests = [ // One option for replacing all text is to specify all tab IDs. { replaceAllText : { containsText : { text : '{{customer-name}}' , matchCase : true , }, replaceText : customerName , tabsCriteria : { tabIds : [ TAB_ID_1 , TAB_ID_2 , TAB_ID_3 ], }, }, }, // Another option is to omit TabsCriteria if you are replacing across all tabs. { replaceAllText : { containsText : { text : '{{date}}' , matchCase : true , }, replaceText : date , }, }, ]; google . options ({ auth : auth }); google . discoverAPI ( 'https://docs.googleapis.com/$discovery/rest?version=v1&key={YOUR_API_KEY}' ) . then ( function ( docs ) { docs . documents . batchUpdate ( { documentId : '1yBx6HSnu_gbV2sk1nChJOFo_g3AizBhr-PpkyKAwcTg' , resource : { requests , }, }, ( err , { data }) = > { if ( err ) return console . log ( 'The API returned an error: ' + err ); console . log ( data ); }); });
Python
customer_name = 'Alice' date = datetime . datetime . now () . strftime ( "%y/%m/ %d " ) requests = [ # One option for replacing all text is to specify all tab IDs. { 'replaceAllText' : { 'containsText' : { 'text' : '{{customer-name}}' , 'matchCase' : 'true' }, 'replaceText' : customer_name , 'tabsCriteria' : { 'tabIds' : [ TAB_ID_1 , TAB_ID_2 , TAB_ID_3 ], }, }}, # Another option is to omit TabsCriteria if you are replacing across all tabs. { 'replaceAllText' : { 'containsText' : { 'text' : '{{date}}' , 'matchCase' : 'true' }, 'replaceText' : str ( date ), } } ] result = service . documents () . batchUpdate ( documentId = document_id , body = { 'requests' : requests }) . execute ()
Manage templates
For template documents the application defines and owns, create the template using a dedicated account representing the application. Service accounts are a good choice and avoid complications with Google Workspace policies that restrict sharing.
When you create instances of documents from templates, always use end-user credentials. This gives users full control over the resulting document and prevents scaling issues related to per-user limits in Drive.
To create a template using a service account, perform the following steps with the application credentials:
- Create a document using documents.create in the Docs API.
- Update the permissions to allow the document recipients to read it using permissions.create in the Drive API.
- Update the permissions to allow template authors to write to it using permissions.create in the Drive API.
- Edit the template as required.
To create an instance of the document, perform the following steps with the user credentials:
- Create a copy of the template using files.copy in the Drive API.
- Replace values using documents.batchUpdate in the Docs API.

