{
  "id": "h7YubkTUmnZrsMQs",
  "name": "Sync Contacts from Notion to Google Contacts with Group Labels",
  "tags": [],
  "nodes": [
    {
      "id": "9884a0d6-5969-4e36-9d1e-e9026cfd2fae",
      "name": "Get All Contacts from Notion",
      "type": "n8n-nodes-base.notion",
      "position": [
        260,
        240
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "operation": "getAll",
        "returnAll": true,
        "databaseId": {
          "__rl": true,
          "mode": "id",
          "value": "Enter your Notion database ID here."
        }
      },
      "credentials": {},
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "14397583-f0e6-4bc4-9bf1-ac87f80e701a",
      "name": "Find Match Labels",
      "type": "n8n-nodes-base.code",
      "position": [
        1400,
        240
      ],
      "parameters": {
        "jsCode": "// Get raw label from Edit Fields\nconst rawLabel = $('Loop Over Contacts').first().json.label || '';\nconsole.log(\"rawLabel:\", rawLabel);\n\n// Parse if it\u2019s a stringified array, otherwise treat as array or single value\nlet labelNames;\nif (typeof rawLabel === 'string') {\n  try {\n    labelNames = JSON.parse(rawLabel); // Convert \"['Gelatin 180-200']\" to [\"Gelatin 180-200\"]\n  } catch (e) {\n    labelNames = [rawLabel]; // If not valid JSON, treat as single string\n  }\n} else if (Array.isArray(rawLabel)) {\n  labelNames = rawLabel; // Already an array\n} else {\n  labelNames = rawLabel ? [rawLabel] : []; // Fallback\n}\n\nconst contactGroups = $input.first().json.contactGroups || [];\n\nconsole.log(\"labelNames (parsed):\", labelNames);\nconsole.log(\"contactGroups:\", contactGroups);\n\n// Match labels and extract resourceName\nconst matchedLabels = labelNames.map(label => {\n  const group = contactGroups.find(g => \n    g.name.trim().toLowerCase() === label.trim().toLowerCase() && \n    g.groupType === \"USER_CONTACT_GROUP\"\n  );\n  console.log(`Searching for: \"${label}\", Found:`, group);\n  return {\n    name: label,\n    resourceName: group ? [group.resourceName] : null // Wrap resourceName in an array\n  };\n});\n\nconsole.log(\"matchedLabels:\", matchedLabels);\n\nreturn matchedLabels.map(label => ({\n  json: {\n    name: label.name,\n    resourceName: label.resourceName // Now an array like [\"contactGroups/40cf29798a92c131\"]\n  }\n}));"
      },
      "executeOnce": true,
      "typeVersion": 2
    },
    {
      "id": "bc13d96d-951e-4d7a-90ed-af96617647ef",
      "name": "Add Contact to Google Contacts",
      "type": "n8n-nodes-base.googleContacts",
      "position": [
        1880,
        240
      ],
      "parameters": {
        "givenName": "={{ $('Loop Over Contacts').item.json.firstName }}",
        "additionalFields": {
          "group": "={{ $json.resourceName }}",
          "phoneUi": {
            "phoneValues": [
              {
                "type": "home",
                "value": "={{ $('Loop Over Contacts').item.json.phone }}"
              }
            ]
          }
        }
      },
      "credentials": {},
      "executeOnce": false,
      "typeVersion": 1
    },
    {
      "id": "d61f9032-9982-4aaf-ab68-c827c345c14d",
      "name": "Workflow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        -540
      ],
      "parameters": {
        "width": 1600,
        "height": 520,
        "content": "# Sync Notion Contacts to Google Contacts with Group Labels\nThis workflow syncs contacts from a Notion database to Google Contacts, assigning group labels based on Notion properties. It triggers on new or updated contacts, retrieves details (name, phone, labels), checks/creates Google Contact groups, adds the contact, and updates Notion to mark it as synced.\n\n**Setup Instructions:**\n1. Connect Notion and Google Contacts via OAuth2 in n8n\u2019s credential settings.\n2. Set your Notion database ID in the Notion Trigger node (find it in your Notion database URL, e.g., 0427eb01ed3b4947873382c566f23785).\n3. Ensure Notion database has fields: name, phone, labels, and \u201cAdded to Contacts\u201d checkbox.\n4. Test the workflow to confirm syncing.\n\n**Requirements:**\n- Notion account with a contact database.\n- Google Contacts account with OAuth2.\n- **Self-hosted n8n instance required (uses community nodes).**\n\nFor advanced setups, see [Notion\u2019s API guide](https://developers.notion.com/)."
      },
      "typeVersion": 1
    },
    {
      "id": "1c52ad45-98ff-4f32-b58e-81dfe4eda13d",
      "name": "Trigger Explanation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        20
      ],
      "parameters": {
        "color": 6,
        "width": 260,
        "height": 520,
        "content": "Triggers the workflow when a new contact is added or an existing contact is updated in the specified Notion database."
      },
      "typeVersion": 1
    },
    {
      "id": "61818fe5-608c-4410-b8fe-f76a203b0123",
      "name": "Field Mapping Guide",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        440,
        20
      ],
      "parameters": {
        "color": 6,
        "width": 220,
        "height": 400,
        "content": "Maps Notion fields (name, phone, labels, added status) to variables for further processing. Customize here to add more fields like email."
      },
      "typeVersion": 1
    },
    {
      "id": "12fb9b67-4b5a-40b0-90f1-f7e896cd47d9",
      "name": "Label Matching Guide",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1340,
        20
      ],
      "parameters": {
        "color": 6,
        "width": 220,
        "height": 400,
        "content": "Matches Notion labels to existing Google Contact groups, parsing labels from Notion\u2019s property_buy field."
      },
      "typeVersion": 1
    },
    {
      "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "name": "Already Synced Check Guide",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        920,
        20
      ],
      "parameters": {
        "color": 6,
        "width": 220,
        "height": 400,
        "content": "Checks if the contact has already been synced to Google Contacts using the 'Already Added' field in Notion."
      },
      "typeVersion": 1
    },
    {
      "id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
      "name": "Group Existence Check Guide",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1580,
        20
      ],
      "parameters": {
        "color": 6,
        "width": 220,
        "height": 400,
        "content": "Verifies if the specified group label exists in Google Contacts. If not, a new group is created."
      },
      "typeVersion": 1
    },
    {
      "id": "c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f",
      "name": "Create Group Guide",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1580,
        -160
      ],
      "parameters": {
        "color": 6,
        "width": 220,
        "height": 400,
        "content": "Creates a new group in Google Contacts if the specified label doesn\u2019t exist."
      },
      "typeVersion": 1
    },
    {
      "id": "d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a",
      "name": "Add Contact Guide",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1820,
        20
      ],
      "parameters": {
        "color": 6,
        "width": 220,
        "height": 400,
        "content": "Adds the contact to Google Contacts with the specified name, phone, and group labels."
      },
      "typeVersion": 1
    },
    {
      "id": "566b7be5-6090-48eb-acb2-71c0844c240b",
      "name": "Map Notion Contact Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        500,
        240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cf7632d2-9983-4c09-8021-7043b8606c48",
              "name": "firstName",
              "type": "string",
              "value": "={{ $json.name }}"
            },
            {
              "id": "bc1f218c-bd1b-4b07-b812-1569f483a838",
              "name": "label",
              "type": "string",
              "value": "={{ $json.property_buy }}"
            },
            {
              "id": "d62010cd-2768-40a4-9279-c4742575a7bd",
              "name": "phone",
              "type": "string",
              "value": "={{ $json.property_phone }}"
            },
            {
              "id": "71fe5268-8798-4641-9395-1c2295c83ae0",
              "name": "Already Added",
              "type": "string",
              "value": "={{ $json.property_added_to_contacts }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8f91fe10-353f-4a03-8ddf-18c8958188aa",
      "name": "Loop Over Contacts",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        760,
        240
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "2d832694-f231-4201-8432-9d032e000d7f",
      "name": "Fetch Google Contact Groups",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1180,
        240
      ],
      "parameters": {
        "url": "https://people.googleapis.com/v1/contactGroups",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "pageSize",
              "value": "1000"
            }
          ]
        },
        "nodeCredentialType": "googleContactsOAuth2Api"
      },
      "credentials": {},
      "typeVersion": 4.2
    },
    {
      "id": "d9660c1f-9672-4cf0-8196-fee0b0acb8d3",
      "name": "Check Google Contact Group Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        1640,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f8e38a64-ace8-49e8-b400-c6609db670e9",
              "operator": {
                "type": "array",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.resourceName }}",
              "rightValue": "null"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c913cf75-f9eb-4b27-b5f3-5bae32ee0d86",
      "name": "Mark Contact as Synced in Notion",
      "type": "n8n-nodes-base.notion",
      "position": [
        2080,
        240
      ],
      "parameters": {
        "pageId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Get All Contacts from Notion').item.json.url }}"
        },
        "options": {},
        "resource": "databasePage",
        "operation": "update",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Added to Contacts|checkbox",
              "checkboxValue": true
            }
          ]
        }
      },
      "credentials": {},
      "typeVersion": 2.2
    },
    {
      "id": "d8f8f322-26c2-4c22-bc74-22db9c67cfd3",
      "name": "Create New Google Contact Group",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1640,
        40
      ],
      "parameters": {
        "url": "https://people.googleapis.com/v1/contactGroups",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"contactGroup\": {\n    \"name\": \"{{ $json.name }}\"\n  }\n} ",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleContactsOAuth2Api"
      },
      "credentials": {},
      "typeVersion": 4.2
    },
    {
      "id": "8e01eb00-ba8b-495b-bcec-38c50d631357",
      "name": "Check if Contact Already Synced",
      "type": "n8n-nodes-base.if",
      "position": [
        980,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a707ab4a-4300-4626-bc72-d0bd6126f733",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $('Map Notion Contact Fields').item.json['Already Added'].toBoolean() }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7a218d3f-9a76-4f21-a599-f550f3642159",
      "name": "Trigger on New Notion Contact",
      "type": "n8n-nodes-base.notionTrigger",
      "position": [
        40,
        160
      ],
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyWeek"
            }
          ]
        },
        "databaseId": {
          "__rl": true,
          "mode": "id",
          "value": "Enter your Notion database ID here."
        }
      },
      "credentials": {},
      "typeVersion": 1
    },
    {
      "id": "871cfdb2-8353-4347-8b96-23d0deacb3cd",
      "name": "Trigger on Updated Notion Contact",
      "type": "n8n-nodes-base.notionTrigger",
      "position": [
        40,
        360
      ],
      "parameters": {
        "event": "pagedUpdatedInDatabase",
        "pollTimes": {
          "item": [
            {
              "mode": "everyWeek"
            }
          ]
        },
        "databaseId": {
          "__rl": true,
          "mode": "id",
          "value": "Enter your Notion database ID here."
        }
      },
      "credentials": {},
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "c0a0f606-780f-4f03-95d9-6d7ad6c12790",
  "connections": {
    "Find Match Labels": {
      "main": [
        [
          {
            "node": "Check Google Contact Group Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Contacts": {
      "main": [
        [],
        [
          {
            "node": "Check if Contact Already Synced",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map Notion Contact Fields": {
      "main": [
        [
          {
            "node": "Loop Over Contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Google Contact Groups": {
      "main": [
        [
          {
            "node": "Find Match Labels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get All Contacts from Notion": {
      "main": [
        [
          {
            "node": "Map Notion Contact Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger on New Notion Contact": {
      "main": [
        [
          {
            "node": "Get All Contacts from Notion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add Contact to Google Contacts": {
      "main": [
        [
          {
            "node": "Mark Contact as Synced in Notion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Contact Already Synced": {
      "main": [
        [
          {
            "node": "Loop Over Contacts",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch Google Contact Groups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create New Google Contact Group": {
      "main": [
        [
          {
            "node": "Loop Over Contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Contact as Synced in Notion": {
      "main": [
        [
          {
            "node": "Loop Over Contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Google Contact Group Exists": {
      "main": [
        [
          {
            "node": "Create New Google Contact Group",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Add Contact to Google Contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger on Updated Notion Contact": {
      "main": [
        [
          {
            "node": "Get All Contacts from Notion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}