n8n is a powerful workflow automation tool that can connect to any service that exposes an API, including Google Docs. In this post, I’ll walk you through creating a workflow that can automatically post content to a Google Docs document, and add formatting too!
What You’ll Need
- An n8n instance (self-hosted or cloud)
- A Google account
- Basic understanding of workflow automation
Setting Up Google Authentication
Before we can interact with Google Docs, we need to set up authentication. It’s beyond the scope of this post to cover this in detail but the basic steps are:
- In n8n, navigate to the Credentials section
- Click Create Credential
- Select Google Docs OAuth2 API from the list
- Follow the OAuth2 authentication flow to connect your Google account
- Save your credentials
Once you’ve successfully connected to Google Docs it should look something like this:
For comprehensive instructions on setting up Google Docs credentials, you can refer to this guide.
Be warned though, even after referring to the official documentation, if you’re not already familiar with the Google Cloud console it can be a little intimidating and tricky to navigate your way around the platform. I personally read through the docs and watched a few YouTube tutorials to help me setup the proper credentials.
Building the n8n Workflow
Our workflow is fairly simple, and consists of a manual trigger to kick off the workflow, followed by nodes to generate sample data, filter it, and send to Google Docs.
This is actually two workflows in one. It contains two Google Docs nodes but only one is active at a time. We can switch between them to run either one. Let’s cover the nodes used in the workflow.
Trigger Node
This is a standard node to use during testing. The workflow is intiated every time you click on the “Test Workflow” button. This button is always displayed at the bottom (center) of the UI and also appears if you hover over the trigger node.
Data Generation Node
For this simple workflow we just need some sample data to work with, and the Customer Datastore does a good job of this. The output of this node is a JSON array of objects we can use in subsequent nodes.
Edit Fields
The Edit Fields (Set) node is used to remap the generated data fields to new fields. In this case we are just taking the id, name, and description fields from the input data and renaming them.
This step isn’t strictly necessary but is a good example of using n8n nodes to filter the data used in the workflow. Usually this is to simplify the data so we’re only working with the fields needed.
Google Docs Node (#1)
The Googgle Docs1 node is currently inactive so we’ll reactivate it and also deactivate the Aggregate and second Google Docs node, so we maintain only one write operation to the document.
Let’s take a closer look at the Google Docs node now.
The setup is quite simple. First we specify the Google Docs credentials, and then the resource (document), operation (update), and the Google document ID. To get this, go into your Google Drive and create a blank document and copy the ID from the URL (highlighted in the screenshot); then paste into the Doc ID or URL field.
Next we want to determine what data to send to Google Docs. The input data is displayed to the left, and we simply need to specify what we want to extract from each object in the list.
`${$json.customer_name}: ${$json.customer_description}\n` }} {{
This snippet pulls the customer name and description fields for each data object and concatenates it into a string and appends a newline character.
Running the Workflow
When we run the workflow via the manual trigger node it runs through all the nodes from start to finish. If you have the blank Google document open then you’ll see several new lines of data added.
Running the Alternative Google Docs Workflow
Let’s deactivate the Google Docs1 node now, and reactivate the Aggragate and associated Google Docs node. This is very similar to the first workflow except here we’re also using the Aggregate node to convert a list of objects into a single object, aggregating the customer name.
As you can see we now have a customer_name
field in the output containing an array of names. Then, in the second Google Docs node we only have one object so instead of specifying which data to pull from each object we can just collate all the name strings together.
We’re actually doing this twice. First we join all the names together separated by a comma, and then again separated by a newline character, just to show some different ways you compile the data.
When the workflow is run this time, the two collation operations are appended to the Google Doc as shown below. Note how the output of the first workflow is still there at the top of the document.
Real World Uses-Cases
Here are a few use-cases for writing to Google Docs in your production workflows:
- Connect to RSS feeds to log new articles
- Link to Slack to save important messages
- Connect to email to archive important communications
- Log form submissions automatically
Advanced Formatting Options
This is really nice now. We have constructed a straightforward way of writing text data to a Google Doc and have it append to the end of the document.
However, you might have noticed that we have only been writing plain text to our Google document. This is a limitation of the n8n core Google Docs node. You can’t write formatted text unfortunately. So adding bullet points, tables, bold/italic text isn’t possible with this node.
Adding Formatting
There is a workaround however. We can use the HTTP Request node to call the Google Docs API directly but it comes with a little more setup. Let’s create a new workflow that uses the HTTP Request node. The first three nodes are the same as before to trigger the workflow, generate sample data, and edit the fields.
The Code node is needed to dynamically compile a JSON object in the correct format that the Google Docs API expects. You can see the node inputs on the left which are the familiar array of objects, and on the right we have the Google Docs API JSON output.
Here is the JavaScript code to convert the array of objects to the correct format. It adds a header with fixed text, and then adds a newline for each data object. The customer name is also converted to bold text.
const requests = [];
let currentIndex = 1;
// Heading: "Customer Notes" using built-in Heading 1 style
const heading = 'Customer Notes\n';
.push({
requestsinsertText: {
location: { index: currentIndex },
text: heading
};
}).push({
requestsupdateParagraphStyle: {
range: {
startIndex: currentIndex,
endIndex: currentIndex + heading.length
,
}paragraphStyle: {
namedStyleType: 'HEADING_1'
,
}fields: 'namedStyleType'
};
})+= heading.length;
currentIndex
// Loop through each customer
for (const item of $input.all()) {
const name = item.json.customer_name;
const desc = item.json.customer_description;
const line = `${name}: ${desc}\n`;
// Insert line
.push({
requestsinsertText: {
location: { index: currentIndex },
text: line
};
})
// Bold just the name
.push({
requestsupdateTextStyle: {
range: {
startIndex: currentIndex,
endIndex: currentIndex + name.length
,
}textStyle: { bold: true },
fields: 'bold'
};
})
+= line.length;
currentIndex
}
// Return the requests to the HTTP node
return [{ json: { requests } }];
This illustrates a significant disadvantage with rolling our own call to the Google Docs API. Where the n8n core Google Docs node handled appending document content seamlessly, we have to manage this 100% ourselves. When appending new content we’d have to manually find the index for the end of the current content and append there. Due to the way indeing works this could be error prone if the content is not plain text.
One approach could be to look at the core Google Docs node code, and see how the indexing is calculated and implement that in a Code node, or even wrap it up into a completely new custom node. This could work but is outside the scope of this post.
For now we’ll just assume that we are writing formatted text to an empty document so the target index is always assumed to be zero.
HTTP Request Node
Most of the work for this workflow was done in the Code node so all that remains is to use the HTTP Request node to send the generated JSON to the Google Docs API.
Running the Workflow
Clear the Google Doc content and run the workflow. You should see the following output:
This is an effective way of sending formatted content to Google Docs but to make it really useful you’d need to find a way to easily append formatted content as mentioned earlier.
Conclusion
With n8n’s Google Docs integration, you can automate content posting to your documents, saving time and ensuring consistency. The simple workflows presented in this post can be expanded with additional nodes for more complex automations tailored to your specific needs.
Sign-up here for more n8n automation content, updates, and latest news!