Integrating Bubble with Google Sheets lets you read spreadsheet data into your app and write app data back to sheets for reporting. This tutorial covers setting up the Google Sheets API via the API Connector, reading spreadsheet rows into Repeating Groups, writing Bubble data to sheets from workflows, and scheduling bidirectional sync with backend workflows.
Overview: Integrating Bubble with Google Sheets
This tutorial shows you how to connect Bubble to Google Sheets using the Google Sheets API via the API Connector plugin. You will read spreadsheet data into your Bubble app for display, write data from Bubble workflows to sheets for reporting, and set up scheduled sync for keeping both systems in sync.
Prerequisites
- A Bubble app with the API Connector plugin installed
- A Google Cloud Platform account with a project created
- Google Sheets API enabled in your GCP project
- A Google Service Account with a JSON key file
Step-by-step guide
Create a Google Cloud service account and enable the Sheets API
Create a Google Cloud service account and enable the Sheets API
Go to console.cloud.google.com. Create a new project or select an existing one. Navigate to APIs & Services → Library, search for Google Sheets API, and click Enable. Then go to APIs & Services → Credentials, click Create Credentials → Service Account. Name your service account and grant it the Editor role. After creation, click the service account, go to the Keys tab, and create a new JSON key. Download this JSON file — you will need the client_email and private_key values. Finally, share your Google Sheet with the service account's email address (found in the JSON file) to grant it access.
Expected result: You have a service account with Sheets API access and the sheet is shared with the service account email.
Configure the API Connector for Google Sheets
Configure the API Connector for Google Sheets
In Bubble, go to Plugins → API Connector. Click Add another API and name it 'Google Sheets'. For authentication, since Google APIs use OAuth2 with service accounts, the simplest approach is to use a middleware service or generate an access token. Set Authentication to Private key in header. You will need to generate a Bearer token using your service account credentials. Add a shared header: Authorization = Bearer [your_access_token]. Alternatively, use a Google OAuth2 plugin or a middleware like Integromat/Make to simplify authentication. Add the base URL: https://sheets.googleapis.com/v4/spreadsheets.
Pro tip: For simpler setups, use a third-party Bubble plugin like 'Google Sheets' from the plugin marketplace, which handles OAuth automatically. The API Connector approach gives you more control but requires more setup.
Expected result: The API Connector is configured with Google Sheets API authentication and base URL.
Create an API call to read spreadsheet data
Create an API call to read spreadsheet data
In the API Connector under your Google Sheets API, click Add another call. Name it 'Get Sheet Data'. Set the method to GET. Set the URL to: /[spreadsheet_id]/values/[range]. Replace [spreadsheet_id] with a parameter (make it dynamic so you can specify different sheets). Set [range] to the sheet and cell range, e.g., Sheet1!A1:Z1000. Set Use as to Data. Click Initialize call with a real spreadsheet ID and range. Bubble will map the response — the values field contains a list of lists (rows of cells). You can now use this as a Repeating Group data source.
Expected result: The API call returns spreadsheet rows that you can display in a Repeating Group.
Display Google Sheets data in a Repeating Group
Display Google Sheets data in a Repeating Group
Add a Repeating Group to your page with data source: Get data from an external API → Google Sheets - Get Sheet Data. The response returns rows as a list. Inside each Repeating Group cell, use text elements bound to the current cell's values at specific indices. For example, if column A is Name and column B is Email, display Current Cell's values item #1 for Name and Current Cell's values item #2 for Email. Add a refresh button that re-fetches the data to show the latest sheet content.
Expected result: Google Sheets data displays in a Bubble Repeating Group with each row showing the spreadsheet columns.
Write Bubble data to a Google Sheet
Write Bubble data to a Google Sheet
Create another API call named 'Append Row'. Set the method to POST. Set the URL to: /[spreadsheet_id]/values/[range]:append?valueInputOption=USER_ENTERED. Set the body type to JSON and add a body parameter for the row data in the format: {"values": [["value1", "value2", "value3"]]}. Set Use as to Action. Initialize the call with sample data. In your Bubble workflow (e.g., after creating a new record), add a Plugins action → Google Sheets - Append Row, mapping your Bubble data fields to the values array. This appends a new row to the sheet each time the workflow runs.
1{2 "values": [3 [4 "<customer_name>",5 "<customer_email>",6 "<order_total>",7 "<order_date>"8 ]9 ]10}Expected result: Running the workflow adds a new row to your Google Sheet with the specified Bubble data.
Schedule bidirectional sync with a backend workflow
Schedule bidirectional sync with a backend workflow
For automatic syncing, create a backend workflow called 'sync-sheets'. This workflow fetches the latest data from Google Sheets using the Get Sheet Data call, compares it with Bubble database records, and creates or updates records as needed. Schedule this workflow to run at regular intervals (e.g., every hour) using the Schedule API Workflow action with a recursive pattern. For the reverse direction, add an action to the backend workflow that reads recent Bubble records (created or modified since the last sync) and appends them to the Google Sheet. Store the last sync timestamp in an AppSettings Data Type to track synchronization state.
Expected result: Data automatically syncs between Bubble and Google Sheets on a scheduled basis in both directions.
Complete working example
1{2 "API Name": "Google Sheets",3 "Authentication": "Private key in header",4 "Base URL": "https://sheets.googleapis.com/v4/spreadsheets",5 "Shared Headers": {6 "Authorization": "Bearer [access_token] (Private)",7 "Content-Type": "application/json"8 },9 "Calls": [10 {11 "Name": "Get Sheet Data",12 "Method": "GET",13 "URL": "/[spreadsheet_id]/values/[range]",14 "Parameters": {15 "spreadsheet_id": "dynamic",16 "range": "Sheet1!A1:Z1000"17 },18 "Use as": "Data"19 },20 {21 "Name": "Append Row",22 "Method": "POST",23 "URL": "/[spreadsheet_id]/values/[range]:append?valueInputOption=USER_ENTERED",24 "Body": {25 "values": [["<col_a>", "<col_b>", "<col_c>"]]26 },27 "Use as": "Action"28 },29 {30 "Name": "Update Cell",31 "Method": "PUT",32 "URL": "/[spreadsheet_id]/values/[range]?valueInputOption=USER_ENTERED",33 "Body": {34 "values": [["<new_value>"]]35 },36 "Use as": "Action"37 }38 ]39}Common mistakes when connecting Bubble with Google Sheets
Why it's a problem: Not sharing the Google Sheet with the service account email
How to avoid: Share the target Google Sheet with the service account email address (found in the JSON key file) with Editor permissions
Why it's a problem: Fetching the entire spreadsheet on every page load
How to avoid: Limit the range parameter to only the rows you need, or cache the data in Bubble's database and refresh on a schedule
Why it's a problem: Hardcoding the spreadsheet ID instead of making it dynamic
How to avoid: Make the spreadsheet_id a dynamic parameter so it can be set per workflow or page
Best practices
- Cache Google Sheets data in your Bubble database to reduce API calls and improve page load speed
- Use a backend scheduled workflow for sync rather than fetching data on every page load
- Limit the range in API calls to only the columns and rows you need
- Make spreadsheet_id a dynamic parameter for flexibility across multiple sheets
- Store the service account credentials securely — never expose the private key in client-side calls
- Use valueInputOption=USER_ENTERED when writing data so Google Sheets interprets formulas and formats
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to integrate my Bubble.io app with Google Sheets to read customer data from a spreadsheet and write new orders back to it. Help me set up the Google Sheets API with a service account and configure the API Connector calls.
Set up an API Connector call to read data from a Google Sheet and display it in a Repeating Group. Then create another call to append a new row when a form is submitted. The sheet has columns: Name, Email, Phone, and Signup Date.
Frequently asked questions
Can I use a Google Sheets plugin instead of the API Connector?
Yes. Several Bubble plugins handle Google Sheets integration with built-in OAuth. They are easier to set up but may have limitations on batch operations or specific API features. The API Connector gives you full control.
How do I handle Google API token expiration?
Google service account tokens expire after 1 hour. Use a backend workflow to refresh the token periodically, or use a middleware service like Make or Zapier that handles token management automatically.
Can I update specific cells instead of appending rows?
Yes. Use the PUT method with the values endpoint and specify the exact cell range (e.g., Sheet1!B5). This overwrites the specified cells with new values.
Is there a limit to how much data I can read from Google Sheets?
Google Sheets API has a limit of 10 million cells per spreadsheet and 60 requests per minute per user. For large datasets, paginate your reads or consider migrating to a proper database.
Can RapidDev help set up Google Sheets integration in Bubble?
Yes. RapidDev can configure the complete Google Sheets integration including API authentication, read/write operations, scheduled sync, and error handling for reliable data exchange between Bubble and your spreadsheets.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation