Google Sheets and Salesforce Integration: Sync Data Both Ways
Connect Google Sheets and Salesforce - Salesforce Connect, the native G Suite app, iPaaS, or custom. Bulk imports, exports, two-way sync, and limits.
Jump to a section
You can connect Google Sheets and Salesforce in four ways: the Salesforce-built G Suite integration, Salesforce Data Loader for batch imports, an iPaaS platform for ongoing sync, or a custom build via APIs. For one-off imports, use Data Loader. For ongoing scheduled exports, use the G Suite integration or an iPaaS. For two-way real-time sync, you almost always want iPaaS.
This guide walks through each path, what’s realistic, and the limits that bite - because Google Sheets is not a database, and pretending it is causes problems at scale.
The 60-second answer
The right path depends on direction and frequency:
- Salesforce → Sheets, one-off report export: native Reports export (CSV), or Connected Apps + scheduled email
- Salesforce → Sheets, scheduled refresh: native G Suite integration, or iPaaS scheduled workflow
- Sheets → Salesforce, one-time bulk import: Data Loader (free, Salesforce-supplied) or Data Import Wizard
- Sheets → Salesforce, ongoing two-way sync: iPaaS (Zapier, Make, n8n) or custom
- Sheets as a live “virtual table” inside Salesforce: Salesforce Connect with an OData provider (advanced)
The four integration paths
Path 1: Native Salesforce + G Suite
Salesforce ships a Google Workspace integration that handles Gmail, Calendar, and some Sheets functionality. For Sheets specifically:
- Salesforce Reports → Google Sheets export - exports report results as a Google Sheet (one-off)
- Tableau CRM (formerly Einstein Analytics) → Sheets - for analytics dashboards
- Lightning App Builder + a Sheets embed component - embeds a sheet as a tile in a Salesforce record page (display only, no sync)
What this isn’t: a fully featured two-way sync between specific sheets and specific Salesforce objects. The native integration is more about “embed/export” than “sync.”
Path 2: Data Loader (Salesforce’s free tool)
Salesforce Data Loader is a free desktop application from Salesforce for bulk insert/update/upsert/delete operations. It reads and writes CSVs. To use it with Google Sheets, you export the sheet as CSV, run Data Loader, and (for the other direction) export Salesforce data as CSV and import to Sheets.
Pros: Free, official, handles up to 5 million records, supports the Bulk API.
Cons: Manual or scheduled-via-CLI only. Not real-time. CSV intermediary step. Best for one-off imports and scheduled batch jobs.
There’s also Data Import Wizard in the Salesforce UI for smaller imports (under 50,000 records, more limited object support).
Path 3: iPaaS
This is where most ongoing-sync use cases live. Zapier, Make, n8n, and Workato all have Google Sheets and Salesforce connectors.
Common workflow shapes:
- “New row in Sheet → Create Lead in Salesforce” (lead intake from manual entry or imported lists)
- “Salesforce Opportunity stage changes → Append row to a ‘pipeline log’ sheet”
- “Daily at 6am, pull all Opportunities updated yesterday → Update or insert rows in Sheet”
- “Sheet row updated → Update the corresponding Salesforce record (by matching ID)”
Pros: Real-time or scheduled, two-way capable, supports filtering and transformation, can fan out to other systems.
Cons: Per-task / per-execution pricing scales with volume. Google Sheets API has hard rate limits (300 read requests / minute / project default) that can throttle high-volume syncs.
Path 4: Salesforce Connect with OData
For the advanced use case where you want a Google Sheet to appear as a Salesforce external object (queryable like a real table without copying data), use Salesforce Connect with an OData adapter that wraps Google Sheets. There are a few third-party OData adapters (CData, Skyvia, etc.) that present a Sheet as an OData endpoint.
Pros: No data copy - the Sheet is queried live from Salesforce. Good when you have reference data in Sheets and don’t want to duplicate.
Cons: Salesforce Connect is an Enterprise/Unlimited Edition feature with per-user licensing. Performance varies - Sheets isn’t designed as a query backend. Adapter cost is additional.
What syncs in each direction
Salesforce → Google Sheets
| Data | Difficulty |
|---|---|
| Lead/Contact/Account list | Easy |
| Opportunity report | Easy |
| Custom object data | Easy if standard fields, harder if complex relationships |
| Activity history | Medium - schema is awkward |
| Attachments | Hard - Sheets isn’t built for files |
| Real-time row updates | Medium - needs iPaaS with Salesforce Streaming API or webhook trigger |
Google Sheets → Salesforce
| Data | Difficulty |
|---|---|
| Bulk Lead import | Easy with Data Loader or Import Wizard |
| Bulk Contact update by external ID | Easy with Data Loader (upsert mode) |
| Row-by-row create on new row | Easy with iPaaS |
| Update existing Salesforce record from edited Sheet row | Medium - needs matching key (Salesforce ID column in Sheet) |
| Delete records | Medium - usually require explicit “delete” flag column to prevent accidents |
Step-by-step: ongoing two-way sync with n8n
This is the most common ask. Setup using n8n (works similarly on Make/Zapier):
1. Plan your matching key
Decide what uniquely identifies a row. Best: the Salesforce record ID. Add a column in your sheet called salesforce_id. New rows leave it blank; the sync fills it after creating the record.
2. Pick your direction(s)
For a true two-way sync, you’ll build two workflows:
- Sheet → Salesforce: triggered when a row is added or edited
- Salesforce → Sheet: triggered when the matching Salesforce record changes
3. Build the Sheet → Salesforce workflow
In n8n:
- Trigger: Google Sheets Trigger node, watching for new/updated rows in a specific sheet/tab
- Branch: IF node - does the row have a
salesforce_id?- Yes → Salesforce node, operation “Update,” map row fields to Salesforce fields
- No → Salesforce node, operation “Create,” then write the returned ID back to the sheet via a Google Sheets node (Update Row)
4. Build the Salesforce → Sheet workflow
- Trigger: Salesforce Trigger node (uses Streaming API / PushTopics) or a Schedule node + Salesforce query for recently updated records
- For each record: lookup by
salesforce_idin the sheet- Found → update the row
- Not found → append a new row with the Salesforce ID
5. Handle conflicts
What if both sides edit at the same time? You need a rule:
- Salesforce wins - simplest. Sheet edits during the conflict window get overwritten.
- Most recent wins - compare
LastModifiedDateon Salesforce vs. an “updated_at” column in the sheet. - Lock the sheet during sync - minimal but disruptive UX.
Most teams pick Salesforce wins for safety.
6. Add error handling
Salesforce will reject records that fail validation. Sheet rows can have typos that break the sync. Add an error workflow that logs failed rows to a separate “sync_errors” tab so someone can triage.
Common pitfalls
Sheets isn’t a database
People treat Sheets like a database. It’s not. Hard ceilings to know:
- 10 million cells per spreadsheet (across all tabs)
- 18,278 columns max per tab
- Performance degrades meaningfully past ~50,000 rows in a tab
- Google Sheets API: 300 read requests per minute per project (default)
If your data is over 100K rows or growing fast, plan to migrate to a real database (Airtable, Postgres, BigQuery).
Matching keys
The number one bug: rows in Sheets without a stable Salesforce ID. After the first edit, you can’t tell if it’s a new record or an update. Always create the ID column at the start and treat it as authoritative.
Column shifts
Someone manually inserts a column in the sheet → the sync workflow that expects column index 5 now reads column 6. Use named ranges or column letters that don’t shift, or reference columns by header name.
Date and number formats
Google Sheets stores dates as serial numbers, displays them as strings. Salesforce expects ISO 8601. Mismatched formats cause silent sync failures. Test with the actual data, not your idealized example.
Picklists
If Sheet values don’t exactly match Salesforce picklist options, the create/update fails. Standardize the values in the sheet (use Data Validation in Sheets to restrict input to the allowed picklist values).
Rate limits
A 50,000-row initial sync at 300 reads/minute is 167 minutes. Plan for it. Use batch writes (Salesforce Bulk API on the Salesforce side, batch update on the Sheets side) where the iPaaS supports it.
Triggers vs. polls
Google Sheets API doesn’t push events on every change reliably. iPaaS “trigger on new row” features are usually polls (every 1-15 minutes). True real-time sync from Sheets is hard. If you need it, consider switching the input layer to a Form (Google Forms / Tally / Typeform) which can webhook on submit.
Pricing
| Path | Cost |
|---|---|
| Native G Suite features | Free (included with Salesforce + Google Workspace) |
| Data Loader | Free |
| Data Import Wizard | Free |
| Zapier | $30-$500+/month |
| Make | $10-$300+/month |
| n8n Cloud | $25-$500+/month |
| n8n self-hosted | $30-$100/month |
| Salesforce Connect (Enterprise/Unlimited) | Add-on licensing |
| OData adapter for Sheets | $50-$300+/month (varies by vendor) |
When to use which path
| Use case | Recommended path |
|---|---|
| One-time data load (Sheet → Salesforce) | Data Loader or Data Import Wizard |
| Scheduled report export (Salesforce → Sheet) | Native G Suite or iPaaS schedule |
| Real-time create on new sheet row | iPaaS (n8n, Make, Zapier) |
| Two-way sync, low volume (<10K rows, <100 edits/day) | iPaaS |
| Two-way sync, high volume | Custom + Salesforce Bulk API |
| Sheet as virtual table inside Salesforce | Salesforce Connect + OData adapter |
| One-off data cleanup project | Data Loader + manual review |
Related reading
- Salesforce and HubSpot integration
- Slack and Salesforce integration
- Sales automation services
- Operations automation - for data ops use cases
- Best CRM for AI automation
- n8n automation guide
- Workflow cost calculator
- Efficiency Scorecard
Spreadsheets are where automation gets messy - they’re flexible, which means they collect technical debt fast. The Efficiency Scorecard helps you identify which “sheet-based process” should be the next thing automated properly.