Sync

Notion tasks to Google Calendar events in n8n

Every 15 minutes, turns Notion tasks with a due date into all-day Google Calendar events, writes the event id back, and deletes the event when the task is done.

Trigger
Schedule Trigger, every 15 minutes
Nodes
9
Requires
Notion, Google Calendar
Category
Sync
From the course
Notion, Airtable and Google Workspace
Published
2026-09-10

Node types used

  • Schedule Trigger
  • Notion
  • Loop Over Items
  • Google Calendar
Workflow diagram: Notion tasks to Google Calendar events in n8nloopSchedule TriggerTasks needing an eventLoop Over ItemsClaim the taskCreate calendar eventWrite event ID backCompleted tasks with …Completed tasks with an eventDelete calendar eventClear event ID
TriggerActionLogic

What it does

A task database with due dates is only useful if the due dates are somewhere you actually look, which for most people is a calendar. The naive version of this creates a duplicate event every time it runs, and leaves ghost events behind for tasks that have since been finished.

A Schedule Trigger every 15 minutes fans out to two independent branches. The create branch queries Notion for pages where Due Date is not empty, Status is not Done, and the Calendar Event ID property is empty, then loops one page at a time. Before it calls Google at all, it writes the string pending: plus the current execution id into that Calendar Event ID property, which takes the page out of the query the next run will make. Only then does it create an all-day Google Calendar event whose summary is the page title, whose start is the due date and whose end is the due date plus one day, and write the real event id back over the pending marker. The cleanup branch queries for pages where Status is Done, Calendar Event ID is not empty and does not contain pending:, deletes the matching Google Calendar event with errors set to continue so an already-deleted event does not stop the run, and clears the Calendar Event ID property on the page.

Only the title and the due date cross over. Nothing reads calendar edits back into Notion, so moving an event in Google Calendar does not change the Notion due date, and changing a due date in Notion does not move an event that already exists.

Node by node

  1. 1

    Schedule Trigger Fires every 15 minutes and feeds both branches at once.

  2. 2

    Tasks needing an event Queries the Notion database for pages where Due Date is not empty AND Status does not equal Done AND Calendar Event ID is empty. Returns all matches.

  3. 3

    Loop Over Items Batch size one, so each task is claimed and created individually rather than as a bulk write.

  4. 4

    Claim the task Writes pending:{{ $execution.id }} into the Calendar Event ID property before any calendar call. That single write is what stops a slow run and the next scheduled run from both creating an event for the same task.

  5. 5

    Create calendar event Creates an event on the chosen calendar with allday yes, summary taken from the page title property, start set to the Due Date start value and end set to that date plus one day.

  6. 6

    Write event ID back Overwrites the pending marker on the Notion page with the real Google Calendar event id, then returns to the loop.

  7. 7

    Completed tasks with an event The other branch. Queries Notion for pages where Status equals Done AND Calendar Event ID is not empty AND does not contain pending:, so half-finished claims are never treated as real events.

  8. 8

    Delete calendar event Deletes the event whose id is stored on the page. onError is set to continue on the regular output, so an event a person already deleted by hand does not fail the run.

  9. 9

    Clear event ID Empties the Calendar Event ID property on the Notion page so the record is clean.

Setup after import

  1. 1

    Create a Notion internal integration credential and select it on all five Notion nodes, then share the task database with that integration.

  2. 2

    Create a Google Calendar OAuth2 credential and select it on both Google Calendar nodes.

  3. 3

    Replace REPLACE_WITH_YOUR_CALENDAR_ID on both Google Calendar nodes with the calendar you want the events on.

  4. 4

    Replace the Notion database URL on both query nodes. The export ships with https://www.notion.so/YOUR_NOTION_DATABASE_ID?v=YOUR_VIEW_ID.

  5. 5

    Add three properties to the Notion database with these exact names: Due Date (date), Status (status, with a Done option) and Calendar Event ID (rich text). The filters reference the names literally.

Limits

  • Title and due date only. No description, no time of day, no attendees: every event is all day.

  • A due date changed after the event exists does not move the event.

  • Nothing reads Google Calendar back into Notion.

  • If a run fails between Claim the task and Write event ID back, the page keeps its pending: marker and is excluded from both branches until someone clears it.

Download the workflow

The 9 node export as n8n reads it. Credential ids, personal values and real endpoints are replaced with placeholders, so nothing here can reach an account that is not yours. No email, no account.

Download notion-tasks-to-google-calendar.json

Get help with this in the community

If the import fails, if a node errors on the first run, or if you want to point this at a service it does not cover yet, post it in the free House of Loops community. Say which template it is and paste the error. Shannon Atkinson answers, and the answer stays there for the next person who hits the same thing.

Ask in the community