# Sheets Crm Sync

> Sync data between Google Sheets and a CRM (HubSpot/Salesforce) — push sheet rows as contacts/deals, or pull CRM records into a sheet for reporting. Use on "sync this sheet to HubSpot", "pull my pipeline into Sheets", or "build a weekly CRM report".

- Skill: `composio-community/sheets-crm-sync` (Agent Skill)
- Install (CLI): `npx skillmds@latest add composio-community/sheets-crm-sync`
- Raw SKILL.md: https://api.skillmd.com/api/skills/composio-community/sheets-crm-sync/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: composio-community (https://skillmd.com/u/composio-community)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/composio-community/sheets-crm-sync

---


# Google Sheets ↔ CRM Sync

Move records between Google Sheets and HubSpot/Salesforce via Composio.

## Workflow

1. **Pick a direction.** Sheet → CRM (import) or CRM → Sheet (report)?
2. **Link both toolkits:**
   ```bash
   composio link googlesheets
   composio link hubspot   # or salesforce
   ```
3. **Read the sheet:**
   ```bash
   composio execute GOOGLESHEETS_BATCH_GET -d '{
     "spreadsheet_id": "1abc...",
     "ranges": ["Leads!A1:F500"]
   }'
   ```
4. **Map columns** explicitly: ask the user for sheet_col → CRM_property pairs. Never guess.
5. **Import or export**:
   - Sheet → CRM: iterate rows, `composio execute HUBSPOT_CREATE_A_CONTACT -d '{...}'` per row, write result (id, status) back to sheet.
   - CRM → Sheet: pull CRM records, build a 2D array, then:
     ```bash
     composio execute GOOGLESHEETS_BATCH_UPDATE -d '{
       "spreadsheet_id": "1abc...",
       "data": [{ "range": "Pipeline!A2", "values": [[...]] }]
     }'
     ```
6. **Timestamp the sync.** Write `last_synced_at` into a header cell so the user sees freshness.

## Reporting recipes

- **Weekly pipeline report:** Pull all open opps → group by stage → write to `Report!A1` with columns: Stage, Count, $Amount, Avg Age.
- **New signups log:** Append each new HubSpot contact created in the last 24h to an "Intake" tab.

## Guardrails

- For Sheet → CRM imports: dedupe on email before creating. Ask before creating > 50 records.
- Never overwrite a sheet without making a backup tab (`<tab>_backup_<date>`).
- If column mapping is ambiguous, stop and ask — bad mappings silently corrupt the CRM.

