#n8n: Sync WhatsApp Messages to Google Sheets
Your WhatsApp messages contain customer gold. Buying patterns. Common questions. Feature requests. Complaints. Everything you need to improve your product.
It's trapped in a chat app. No search. No analysis. No team access. Flying blind.
The fix: n8n webhook automation that syncs every WhatsApp message to Google Sheets in real-time. Searchable archive. Message volume analytics. Trend identification. GDPR-compliant exports.
This guide shows you the complete pipeline. No backend server. Thirty-minute setup. MoltFlow webhooks forward messages to n8n, n8n appends to Google Sheets, you get instant analytics. Runs forever. Works with 500+ n8n integrations for CRM sync, Slack alerts, and AI analysis.
What You're Building
By the end of this guide, you'll have a system that:
- Captures every incoming and outgoing WhatsApp message in real-time
- Logs each message to Google Sheets with timestamp, sender, content, and session
- Filters by session or message type (text, image, audio)
- Visualizes message volume over time with Google Sheets charts
- Exports data for analysis in Excel, Python, or BI tools
The entire flow is automated. Messages appear in your spreadsheet within seconds of being sent or received.
Why Log Messages to Google Sheets?
WhatsApp is great for communication. Terrible for analytics.
Google Sheets gives you:
- Search: Find messages by keyword, date range, or sender
- Filtering: Show only specific sessions or message types
- Charts: Visualize message volume, response times, common keywords
- Sharing: Give your team read-only access to the archive
- Export: Download as CSV for analysis in other tools
- Formulas: Calculate metrics like average response time, messages per day
Plus, Google Sheets is free and accessible from anywhere. No database setup. No SQL queries. Just a familiar spreadsheet interface.
Use Cases
Here's what you can do with a WhatsApp message archive:
Customer Support Analytics
Log all support conversations. Calculate:
- Average messages per ticket
- Response time per agent
- Most common support topics (keyword frequency)
- Peak support hours
Lead Quality Analysis
Track which leads convert by correlating WhatsApp conversations with CRM data:
- Do leads who ask about pricing convert more than those who ask about features?
- How many messages does it take to close a deal?
- Which sales reps have the highest close rate?
Content Research
Mine customer language for:
- Questions they ask (FAQ candidates)
- Words they use (copy for landing pages)
- Problems they mention (product roadmap ideas)
Compliance and Archival
Some industries require logging all customer communications. WhatsApp doesn't provide built-in export. This workflow creates a timestamped, immutable record.
Prerequisites
Before you start, make sure you have:
- MoltFlow account with active WhatsApp session (sign up)
- n8n instance (self-hosted or n8n.cloud) — installation guide
- Google account for Google Sheets
- MoltFlow API key (Dashboard → Settings → API Keys)
New to n8n + MoltFlow? Start here: Connect MoltFlow to n8n: WhatsApp Automation Without Code
Step 1: Set Up Your Google Sheet
First, create the spreadsheet where messages will be logged.
Create New Sheet
Go to Google Sheets and create a new blank spreadsheet. Name it something like "WhatsApp Message Archive".
Set Up Columns
In the first row, create these column headers:
| A | B | C | D | E | F | G | H |
|---|---|---|---|---|---|---|---|
| Timestamp | Direction | From | To | Message | Type | Session | Message ID |
What each column means:
- Timestamp: When message was sent (ISO format for sorting)
- Direction: "incoming" or "outgoing"
- From: Sender phone number or name
- To: Recipient phone number or chat ID
- Message: The actual message text
- Type: "text", "image", "audio", "video", "document"
- Session: Which MoltFlow session handled this message
- Message ID: Unique identifier from WhatsApp
Format the Sheet
Make it easier to read:
- Freeze the header row (View → Freeze → 1 row)
- Set Timestamp column to date/time format
- Set column widths (Timestamp: 150px, Message: 400px, others: 120px)
- Add filter buttons (Data → Create a filter)
Share with n8n
You need to give n8n write access to this sheet.
Option A: OAuth (Recommended)
In n8n, go to Credentials → Add Credential → Google Sheets OAuth2 API. Follow the authorization flow. This gives n8n permission to write to any sheet in your Google account.
Option B: Service Account
Create a service account in Google Cloud Console, download the JSON key, and share your sheet with the service account email. More secure but more setup.
For this guide, we'll use OAuth (simpler).
Step 2: Configure MoltFlow Webhook
You need MoltFlow to forward messages to your n8n workflow.
Create Webhook in MoltFlow
Go to MoltFlow Dashboard → Webhooks and click "Create Webhook".
URL: We'll fill this in after creating the n8n workflow
Events to subscribe:
message(incoming messages)message.any(includes outgoing messages)
Subscribe to message.any if you want to log both sides of conversations. If you only care about incoming messages, just use message.
Sessions: Select the session(s) you want to log (or leave blank for all)
Save the webhook (we'll activate it after setting up n8n).
Step 3: Create n8n Workflow
Now build the workflow that receives messages and writes to Google Sheets.
Add Webhook Node
In n8n, create a new workflow. Add a Webhook node.
Settings:
- HTTP Method: POST
- Path:
whatsapp-to-sheets - Response Mode: Last Node
- Response Code: 200
Activate the workflow. Copy the webhook URL that n8n generates:
https://your-n8n.com/webhook/whatsapp-to-sheetsGo back to MoltFlow webhook config and paste this URL. Activate the webhook.
Test Webhook
Send a test message to your WhatsApp session. Check the n8n execution log. You should see a payload like this:
{
"event": "message",
"session": "my-session",
"payload": {
"id": "msg_abc123",
"from": "[email protected]",
"fromName": "John Doe",
"to": "me",
"body": "Hey, what's your pricing?",
"timestamp": "2026-02-03T14:30:00Z",
"type": "chat",
"hasMedia": false
}
}Perfect. Now let's parse this data and write it to Google Sheets.
Step 4: Parse Message Data
After the Webhook node, add a Set node named "Format for Sheets".
This extracts the fields we care about and formats them for the spreadsheet.
Configure Fields
| Field Name | Expression | Notes |
|---|---|---|
timestamp | ={{ $json.payload.timestamp }} | ISO 8601 format |
direction | ={{ $json.event === 'message.any' && $json.payload.fromMe ? 'outgoing' : 'incoming' }} | Detect direction |
from | ={{ $json.payload.fromName || $json.payload.from }} | Use name if available |
to | ={{ $json.payload.to || 'N/A' }} | Recipient |
message | ={{ $json.payload.body || '[Media message]' }} | Text or placeholder |
type | ={{ $json.payload.type || 'unknown' }} | Message type |
session | ={{ $json.session }} | Session name |
messageId | ={{ $json.payload.id }} | Unique ID |
The direction expression checks if the message came from you (fromMe: true) to determine if it's outgoing.
Step 5: Add Google Sheets Node
After the Set node, add a Google Sheets node.
Operation: Append Row
Document: Select "By URL" and paste your Google Sheets URL
Alternatively, use "By ID" and extract the sheet ID from the URL:
https://docs.google.com/spreadsheets/d/{SHEET_ID}/editSheet Name: Sheet1 (or whatever you named your sheet)
Columns:
Map each field to the corresponding column:
| Column | Value |
|---|---|
| A (Timestamp) | ={{ $json.timestamp }} |
| B (Direction) | ={{ $json.direction }} |
| C (From) | ={{ $json.from }} |
| D (To) | ={{ $json.to }} |
| E (Message) | ={{ $json.message }} |
| F (Type) | ={{ $json.type }} |
| G (Session) | ={{ $json.session }} |
| H (Message ID) | ={{ $json.messageId }} |
Credentials: Select your Google Sheets OAuth2 credential (the one you set up in Step 1)
Save the workflow.
Step 6: Test the Complete Flow
Send another test message to your WhatsApp session.
Within seconds, it should appear in your Google Sheet.
Check:
- Row appears in spreadsheet
- Timestamp is formatted correctly
- Direction shows "incoming" or "outgoing"
- Message text is captured accurately
- Session name is correct
If something's wrong, check n8n's execution log for errors. Common issues:
- Google Sheets credentials not authorized
- Sheet ID incorrect
- Column mapping mismatched
Step 7: Add Optional Filtering
You might not want to log EVERY message. Maybe you only care about specific sessions, or only text messages (no images/videos).
Filter by Session
Add an If node after the Set node, before Google Sheets.
Condition:
{{ ['session-1', 'session-2'].includes($json.session) }}Replace session-1 and session-2 with the sessions you actually want to log.
Only the true path connects to Google Sheets. The false path can connect to a different sheet or just end.
Filter by Message Type
Want to log only text messages? Add this condition:
{{ $json.type === 'chat' }}Or exclude images and videos:
{{ !['image', 'video'].includes($json.type) }}You can combine multiple conditions with AND/OR logic.
Complete n8n Workflow JSON
Here's the full workflow you can import into n8n:
{
"name": "WhatsApp to Google Sheets - MoltFlow",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "whatsapp-to-sheets",
"responseMode": "lastNode"
},
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [250, 300]
},
{
"parameters": {
"values": {
"string": [
{
"name": "timestamp",
"value": "={{ $json.payload.timestamp }}"
},
{
"name": "direction",
"value": "={{ $json.event === 'message.any' && $json.payload.fromMe ? 'outgoing' : 'incoming' }}"
},
{
"name": "from",
"value": "={{ $json.payload.fromName || $json.payload.from }}"
},
{
"name": "to",
"value": "={{ $json.payload.to || 'N/A' }}"
},
{
"name": "message",
"value": "={{ $json.payload.body || '[Media message]' }}"
},
{
"name": "type",
"value": "={{ $json.payload.type || 'unknown' }}"
},
{
"name": "session",
"value": "={{ $json.session }}"
},
{
"name": "messageId",
"value": "={{ $json.payload.id }}"
}
]
}
},
"name": "Format for Sheets",
"type": "n8n-nodes-base.set",
"position": [450, 300]
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_SHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Sheet1",
"mode": "list"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"A": "={{ $json.timestamp }}",
"B": "={{ $json.direction }}",
"C": "={{ $json.from }}",
"D": "={{ $json.to }}",
"E": "={{ $json.message }}",
"F": "={{ $json.type }}",
"G": "={{ $json.session }}",
"H": "={{ $json.messageId }}"
}
},
"options": {}
},
"name": "Append to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [650, 300],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "Google Sheets account"
}
}
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Format for Sheets",
"type": "main",
"index": 0
}
]
]
},
"Format for Sheets": {
"main": [
[
{
"node": "Append to Google Sheets",
"type": "main",
"index": 0
}
]
]
}
}
}Before importing:
- Replace
YOUR_SHEET_IDwith your actual Google Sheets ID - Configure Google Sheets OAuth2 credentials in n8n
Building a Dashboard
Now that messages are flowing into Google Sheets, let's build some analytics.
Message Volume Over Time
Create a new sheet tab called "Dashboard".
In cell A1, add a formula to count messages per day:
=QUERY('Sheet1'!A:H, "SELECT A, COUNT(A) WHERE A IS NOT NULL GROUP BY A ORDER BY A", 1)This creates a table of dates and message counts.
Create a chart:
- Select the query results
- Insert → Chart
- Chart type: Line chart
- X-axis: Date
- Y-axis: Message count
You now have a visual timeline of message volume.
Messages by Direction
Count incoming vs outgoing:
=QUERY('Sheet1'!A:H, "SELECT B, COUNT(B) WHERE B IS NOT NULL GROUP BY B", 1)Create a pie chart:
- Chart type: Pie chart
- Shows percentage breakdown of incoming vs outgoing
Top Senders
Find who messages you most:
=QUERY('Sheet1'!A:H, "SELECT C, COUNT(C) WHERE C IS NOT NULL GROUP BY C ORDER BY COUNT(C) DESC LIMIT 10", 1)Create a bar chart:
- X-axis: Sender name
- Y-axis: Message count
Average Response Time
Calculate how long it takes you to respond to incoming messages.
In a new column (column I), add this formula:
=IF(B2="outgoing", MINUS(A2, VLOOKUP(H2, {H:H, A:A}, 2, FALSE)), "")This finds the previous incoming message with the same thread and calculates time difference.
Then average this column:
=AVERAGE(I:I)Message Type Breakdown
How many text vs image vs audio messages?
=QUERY('Sheet1'!A:H, "SELECT F, COUNT(F) WHERE F IS NOT NULL GROUP BY F ORDER BY COUNT(F) DESC", 1)Create a bar chart showing distribution.
Advanced: Add Full-Text Search
Google Sheets has built-in search, but it's slow on large datasets. Here's how to build a custom search interface.
Create Search Sheet
Add a new tab called "Search".
Cell A1 (label): "Search for:"
Cell B1 (input): Leave blank (user types search term here)
Cell A3 (formula):
=QUERY('Sheet1'!A:H, "SELECT * WHERE E CONTAINS '" & B1 & "' ORDER BY A DESC", 1)This searches the Message column (E) for whatever text is in B1 and displays all matching rows sorted by date descending.
Usage: Type a keyword in B1, hit Enter, see all messages containing that keyword.
Search by Date Range
Cell A1: "Start Date:" Cell B1: (enter start date)
Cell A2: "End Date:" Cell B2: (enter end date)
Cell A4 (formula):
=QUERY('Sheet1'!A:H, "SELECT * WHERE A >= date '" & TEXT(B1, "yyyy-MM-dd") & "' AND A <= date '" & TEXT(B2, "yyyy-MM-dd") & "' ORDER BY A DESC", 1)Now you can view all messages within a specific date range.
Handling Large Datasets
Google Sheets can handle up to 10 million cells. At ~100 characters per message, that's roughly 100,000 messages before you hit limits.
If you're logging high-volume conversations (thousands per day), you'll need archival strategy.
Monthly Archive Sheets
Instead of appending to one sheet forever, create a new sheet each month.
In n8n, add a Code node before Google Sheets:
const timestamp = $input.first().json.timestamp;
const date = new Date(timestamp);
const sheetName = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
return {
...input.first().json,
sheetName: sheetName
};In Google Sheets node:
- Sheet Name:
={{ $json.sheetName }}
This creates sheets named like "2026-02", "2026-03", etc.
You'll need to manually create each new sheet at the start of the month (or use Google Apps Script to auto-create).
Export Old Data
Once a month, export old sheets to CSV and delete the Google Sheet tab:
- File → Download → CSV
- Store in cloud storage (Google Drive, S3, Dropbox)
- Delete the sheet tab to free up space
Upgrade to Database
If you're logging 10,000+ messages per day, Google Sheets isn't the right tool. Upgrade to:
- Airtable (better for large datasets, still has UI)
- PostgreSQL (full database, requires n8n Postgres node)
- BigQuery (Google's data warehouse, great for analytics)
The n8n workflow structure stays the same — just swap the Google Sheets node for a Postgres/Airtable node.
Troubleshooting
Messages Not Appearing in Sheet
Check:
- Webhook is active in MoltFlow Dashboard
- n8n workflow is activated (not just saved)
- Google Sheets credential is authorized
- Sheet ID is correct
- Column mappings match (A-H)
Debug: Check n8n execution log. Look for errors on the Google Sheets node.
Duplicate Messages
Problem: Same message appears twice in sheet.
Cause: MoltFlow retries failed webhooks. If n8n responds slowly, MoltFlow might retry before getting response.
Solution: Add deduplication. Before appending to sheet, check if Message ID already exists:
// In Code node before Google Sheets
const messageId = $input.first().json.messageId;
const sheet = $('Append to Google Sheets').all(); // Get existing data
const exists = sheet.some(row => row.json.H === messageId); // Check column H
if (exists) {
return { skip: true };
}
return { skip: false };Then add an If node that only appends if {{ !$json.skip }}.
Timestamp Format Wrong
Problem: Timestamps appear as text instead of dates in Google Sheets.
Solution: Make sure Timestamp column is formatted as "Date time" in Google Sheets:
- Select column A
- Format → Number → Date time
If values still appear as text, n8n might be sending strings. Convert to date in the Set node:
={{ new Date($json.payload.timestamp).toISOString() }}Rate Limit Errors
Problem: Google Sheets API returns 429 (too many requests).
Cause: n8n is trying to append too many rows too fast.
Solution: Add a Delay node (500ms) before Google Sheets node. Or use batch mode:
Instead of appending one row per message, batch messages and append in groups of 10-20.
What's Next
You've got a complete WhatsApp message archive and analytics dashboard running on Google Sheets.
Connect MoltFlow to n8n in 15 minutes, configure webhooks for message forwarding, and start building analytics on top of your message data. The workflow template in this guide handles the basic sync—extend it with REST API calls for advanced filtering.
Ready to implement this? Follow our step-by-step guide: Connect MoltFlow to n8n for the foundational webhook setup, then use this guide's workflow template for Google Sheets sync.
Related workflows:
- Connect MoltFlow to n8n: WhatsApp Automation Without Code — n8n basics and setup
- Build a WhatsApp Lead Pipeline with n8n and MoltFlow — Qualify and route leads automatically
- Auto-Reply to WhatsApp Group Messages with n8n — Intelligent group automation
Advanced enhancements:
- Add sentiment analysis to detect angry/happy customers
- Extract contact info (email, phone) with regex and store in separate columns
- Build a "Support Ticket" view that groups messages by conversation thread
- Export to data visualization tools (Tableau, Looker, Metabase)
MoltFlow features to explore:
- Webhook Events — Other events you can log (status changes, media uploads, etc.)
- API Reference — Full API for building custom integrations
Ready to build your message archive? Start your free MoltFlow trial and import this workflow in 5 minutes.
Conclusion
Data trapped in chat apps is useless data.
With this n8n workflow, every WhatsApp conversation becomes searchable, analyzable, and shareable. You can spot trends, track response times, and mine customer language for insights — all in a familiar spreadsheet interface.
Start simple. Log messages for a week. Build a basic dashboard. Once you see the value, expand the workflow — add filtering, create advanced charts, export for machine learning.
Your WhatsApp data has answers. Now you can find them.
Questions? Join the MoltFlow Discord or check out the full documentation.
Now go unlock your message data.
> Try MoltFlow Free — 100 messages/month