Your Contact List Is Lying to You (Here's How to Fix It)

TL;DR: Keep Google Contacts and Notion perfectly synchronized in both directions using n8n. This advanced workflow creates a true two-way sync that detects changes on either platform, updates the other automatically, and even handles deletions gracefully. No more wondering which database has the latest phone number.

Difficulty⭐⭐⭐⭐⭐ (Advanced)
Who's this for?Service providers tracking client data, Notion power users, automation enthusiasts who enjoy complex challenges
Problem it solvesScattered contact information across Google and Notion, manual syncing nightmares, data inconsistency headaches
LinkGet the template
Tools you'll needn8n, Google Contacts, Notion
Setup time45-60 minutes (this is a complex one)
Time saved~2 hours per month + eliminated sync errors

The Contact Database Problem David Doesn't Want to Talk About

David keeps his client contacts in Google Contacts because it syncs with his phone. He also keeps them in Notion because he built this beautiful client dashboard with projects, invoices, and meeting notes all interconnected. The problem? He updates one, forgets to update the other, and ends up with two versions of the truth.

Last month he spent twenty minutes looking for a client's new phone number, absolutely convinced he'd saved it. He had saved it—in Google Contacts. The Notion database still showed the old disconnected line. This is the exact moment when most people either give up on one system entirely or resign themselves to manual double-entry forever.

There's a third option, but it requires accepting that computers are better at repetitive synchronization than humans will ever be.

What This Workflow Does

This n8n workflow creates a genuine two-way sync between Google Contacts and Notion. Not a one-time import. Not a scheduled batch update. A living, breathing synchronization engine that watches both platforms simultaneously and keeps them identical. If you're new to n8n, check out our beginner's tutorial to get started with the basics first.

When you create a contact in Google on your phone, it appears in Notion within seconds. When you update a client's email address in your Notion dashboard, Google Contacts reflects the change immediately. Delete something in either location and it vanishes from both. The workflow even handles edge cases like detecting whether a change came from a human or from itself, preventing infinite update loops.

This is contact management as it should be: invisible, automatic, and reliable enough that you genuinely forget which system you're updating because it doesn't matter anymore. For more advanced automation ideas, see our guide to 10 essential n8n workflows for solopreneurs.

Quick Start Guide

Before diving into the workflow itself, you'll need a Notion database structured to hold contact information. Create a database with properties for name, email, phone numbers, addresses, and whatever other fields matter to your use case. The workflow includes nodes that map Google Contact fields to Notion properties, so you'll want those property names handy.

The workflow operates in two phases. First comes an initial import that pulls all your existing Google Contacts into Notion. This is a one-time bulk operation that populates your Notion database. Once that's complete, the workflow switches to continuous sync mode where it monitors both platforms for changes. You can filter by Google Contact labels if you only want to sync specific groups—useful if you have thousands of contacts but only want your clients in Notion.

Authentication requires connecting both your Google account and Notion workspace to n8n. The workflow uses Google's People API for contact operations and Notion's official API for database manipulation. Once credentials are configured and the initial import completes, the automation runs continuously in the background. If you're just getting started with automation, our AI automation guide for beginners covers the fundamentals.

How It Actually Works (Step by Step)

The workflow splits into three distinct automation paths, each handling a different synchronization scenario.

Path One: Manual Initial Import

The first path handles the initial bulk import from Google to Notion. It starts with a manual trigger that you click once to begin the import. A "Get all contacts" node pulls every contact from Google Contacts using the Google Contacts API. If you're filtering by label, a filter node removes contacts that don't match your criteria—this keeps your Notion database focused on relevant contacts rather than every person you've ever emailed.

Next comes field extraction. Google Contacts returns data in a complex nested structure with arrays for phone numbers, email addresses, and physical addresses. A Set node flattens this structure into simple fields that Notion can understand. Phone numbers become text, addresses become formatted strings, and metadata like ETags (version identifiers) get stored for later conflict detection.

Finally, the workflow creates Notion pages for each contact. It saves the Google Contact ID to each Notion page so future updates know which contact corresponds to which page. This mapping is critical—without it, the two-way sync has no way to match records across platforms.

For Advanced Readers: The ETag system is particularly elegant. Google Contacts assigns each contact a version identifier that changes with every edit. By storing this ETag in Notion, the workflow can detect when a contact has been modified externally and needs re-syncing. It's the same conflict detection strategy that Git uses for file versioning.

Path Two: Notion to Google Sync

The second automation path watches Notion for changes and updates Google accordingly. It uses Notion triggers that fire whenever a database page is created or updated. When you add a new contact in Notion, the workflow checks whether a corresponding Google Contact exists by looking for a stored Google ID. If there's no ID, this is a new contact that needs creating in Google.

The workflow constructs a properly formatted Google Contacts API request with all the contact information from Notion. It creates the contact, receives back a Google Contact ID, and immediately stores that ID in the Notion page. This completes the linkage between the two systems. If you specified a Google Contact label for filtering, it also adds the contact to that label group automatically.

For existing contacts being updated, the workflow retrieves the current Google Contact using the stored ID, compares ETags to detect conflicts, and pushes the Notion changes to Google. After updating, it saves the new ETag back to Notion. This ETag round-trip ensures the workflow knows this update came from itself and won't trigger an infinite sync loop.

There's also deletion handling. If you delete a contact's Notion page, the workflow detects the deletion event and removes the corresponding Google Contact. You can disable this behavior if you prefer deletions to only work one direction.

For Advanced Readers: The workflow uses HTTP Request nodes instead of the built-in Google Contacts node for updates and deletions because the native node doesn't support all required operations. This is a common pattern in advanced n8n workflows—when the pre-built node doesn't do what you need, drop down to raw API calls. The HTTP nodes construct proper OAuth-authenticated requests to Google's People API v1 endpoints.

Path Three: Google to Notion Sync

The third path runs on a schedule (every minute by default) and watches Google Contacts for changes. This is necessary because Google doesn't offer webhooks—there's no way for Google to notify n8n when something changes. Instead, the workflow polls Google's sync API regularly.

Google Contacts provides a sync token system specifically for this use case. The first time you sync, Google returns all contacts plus a sync token. On subsequent syncs, you send that token back and Google returns only contacts that changed since last time. This is vastly more efficient than downloading all contacts repeatedly. Learn more about two-way sync strategies in n8n's official guide.

The workflow stores the sync token in a Notion page (treating Notion as its own state database). Each polling cycle retrieves the token, requests changes from Google, processes any modified or deleted contacts, updates Notion accordingly, then saves the new sync token. It's a continuous loop of "what changed since I last asked?"

Contact deletions from Google also sync to Notion. The Google sync response includes deleted contact IDs. The workflow finds the corresponding Notion pages and deletes them, keeping both databases in agreement about what exists and what doesn't.

For Advanced Readers: The polling interval is configurable. One minute provides near-real-time sync for most use cases, but you could extend it to five or fifteen minutes if you're concerned about API rate limits. Google's quota for the People API is generous (3000 requests per minute), so polling every minute is typically fine unless you're running dozens of other Google integrations simultaneously.

Key Learnings for No-Code Builders

Bidirectional sync requires state management. You can't just blindly copy data back and forth or you'll create update loops where each platform keeps triggering updates on the other infinitely. The ETag system here is the secret—by tracking version identifiers and only updating when they've changed externally, the workflow knows when it caused a change versus when a human did. This is the fundamental pattern for any two-way integration.

Polling isn't dirty when webhooks don't exist. The instinct is to use webhooks for everything because they're "real-time," but many services (including Google Contacts) simply don't offer them. In those cases, polling with sync tokens is the professional solution. Google designed the sync token API specifically for this pattern. Use the tools as they're designed rather than fighting for a webhook that'll never come.

Field mapping is where complexity hides. The actual API calls in this workflow are straightforward—create this, update that, delete the other thing. The hard part is transforming nested Google Contact structures into flat Notion properties and vice versa. Spend time understanding both data models before building integration logic. Draw out the field mappings on paper. The transformation nodes will be the most complex part of any integration workflow.

What's Next: Your Challenge

Here's your mission: Implement this workflow and let it run for a week. Make edits in both systems deliberately. Add a contact on your phone. Update an email in Notion. Delete something in Google. Watch it propagate.

Then extend it. Maybe you want contacts to automatically move to different Notion databases based on tags. Maybe you want new Google Contacts to trigger a welcome email sequence. Maybe you need this same pattern but for syncing tasks between Todoist and Notion, or calendar events between Google Calendar and a project management database.

The core pattern here—triggers on both sides, state management through version tracking, transformation layers for data mapping—applies to any bidirectional sync scenario. Master this workflow and you've mastered a fundamental automation architecture.

And when it's running smoothly and you realize you genuinely can't remember whether you updated that phone number in Google or Notion because both are always correct? That's the moment David still hasn't experienced. But you will.

Now go build something that stays in sync.

Frequently Asked Questions

Can I sync contacts from multiple Google accounts?

Not directly with a single workflow. Each n8n workflow authenticates with one Google account at a time. However, you can duplicate the workflow and connect different Google accounts to separate Notion databases. If you need all contacts in one Notion database, you'd need additional logic to merge contacts and handle potential duplicates across accounts.

What happens if I edit the same contact in both systems before the sync runs?

The workflow uses ETags (version identifiers) to detect conflicts, but it follows a "last write wins" strategy. Whichever platform you edited most recently will overwrite the other. For mission-critical contact data, consider implementing a conflict resolution UI that flags simultaneous edits for manual review, or adjust the polling interval to sync more frequently (every 30 seconds instead of every minute).

Does this workflow count against Google's API rate limits?

Yes, but Google's People API quota is generous: 3,000 requests per minute and 1,200,000 requests per day for most accounts. The workflow uses sync tokens, which means it only requests changed contacts rather than your entire contact list each time. Unless you have thousands of contacts changing simultaneously or multiple heavy integrations running, you're unlikely to hit limits.

Can I filter which contacts sync based on Notion database properties?

The template filters by Google Contact labels during the initial import, but you can extend it to filter based on Notion properties as well. Add a filter node after the Notion trigger that checks for specific tags, categories, or custom fields. For example, you could sync only contacts tagged as "Client" in Notion while ignoring personal contacts.

Last updated: February 13, 2026