{
  "id": "G5BeNYC1cO4PrAej",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Enrich Company Data in Google Sheets with CompanyEnrich",
  "tags": [],
  "nodes": [
    {
      "id": "119d5185-c721-487e-8c80-2e9e58d64ae1",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -160,
        464
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "f5c70be0-e7fb-41be-afd9-c3cfe240654c",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        80,
        464
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1aZXmlXOkyj1hq40mP-6FIXKNDXELs520bg90mCJTmYY/edit#gid=0",
          "cachedResultName": "Sayfa1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1aZXmlXOkyj1hq40mP-6FIXKNDXELs520bg90mCJTmYY",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1aZXmlXOkyj1hq40mP-6FIXKNDXELs520bg90mCJTmYY/edit?usp=drivesdk",
          "cachedResultName": "Ba\u015fl\u0131ks\u0131z e-tablo"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "0770a814-ee02-4d74-a6b2-27c67260fb9d",
      "name": "Filter",
      "type": "n8n-nodes-base.filter",
      "position": [
        288,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e6f0ab3a-c024-488c-bf70-818cf570bbe2",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "Done"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "546d1aea-ee02-42fa-92b7-f98c26dd4b04",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        -176
      ],
      "parameters": {
        "width": 596,
        "height": 516,
        "content": "## \ud83d\ude80 Company Enrichment Workflow\n\nThis workflow automatically populates your Google Sheet with firmographic data based on a company's domain name.\n\n## How it works\n1. **Reads** domains from Google Sheets & **Filters** out completed rows.\n2. **Fetches** data using the CompanyEnrich API.\n3. **Cleans & Maps** the data to your specific Sheet headers.\n4. **Updates** the row with new info.\n\n## Setup steps\n1. Create a Google Sheet with headers: `Domain`, `Status`, and `Last Updated`.\n2. **Add columns for data you want.** The workflow matches API fields to your headers automatically. Examples:\n   * `revenue`\n   * `employees`\n   * `socials_linkedin_url` (Nested fields use underscores)\n   * `location_country_name`\n3. Configure the nodes with your Sheet ID and API Key."
      },
      "typeVersion": 1
    },
    {
      "id": "0b47b632-46a9-4c60-aef6-5a8e8760843b",
      "name": "Input Group",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 600,
        "height": 240,
        "content": "## 1. Input & Validation\nRetrieves data from your spreadsheet and filters out processed rows to save API credits."
      },
      "typeVersion": 1
    },
    {
      "id": "ac8b9957-adb9-4697-8e21-5c63f0e00e94",
      "name": "Enrich Group",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 750,
        "height": 460,
        "content": "## 2. Enrichment & Update\nLoops through domains, fetches data, flattens the JSON structure (e.g. `location.city.name` \u2192 `location_city_name`), and updates matching columns in Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "baf18175-5574-4dac-80ae-131c49136049",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        544,
        464
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "2802e920-0eef-4d36-b60c-08b9b5bfb02b",
      "name": "Update row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        784,
        304
      ],
      "parameters": {
        "columns": {
          "value": {
            "Domain": "={{ $('Get row(s) in sheet').item.json.Domain }}",
            "Status": "={{ $json.status_update }}",
            "Last Updated": "={{ $now.toISO() }}"
          },
          "schema": [
            {
              "id": "Domain",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Domain",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "industries",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "industries",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "employees",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "employees",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "revenue",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "revenue",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "location_country_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "location_country_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "socials_linkedin_url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "socials_linkedin_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Updated",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Last Updated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "logo_url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "logo_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [
            "Domain"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1aZXmlXOkyj1hq40mP-6FIXKNDXELs520bg90mCJTmYY/edit#gid=0",
          "cachedResultName": "Sayfa1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1aZXmlXOkyj1hq40mP-6FIXKNDXELs520bg90mCJTmYY",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1aZXmlXOkyj1hq40mP-6FIXKNDXELs520bg90mCJTmYY/edit?usp=drivesdk",
          "cachedResultName": "Ba\u015fl\u0131ks\u0131z e-tablo"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "3b4bf5ca-b508-4fb3-bec8-751f672e38c7",
      "name": "Data Cleaning (JS)",
      "type": "n8n-nodes-base.code",
      "position": [
        960,
        480
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// 1. Get input data from the API (previous node)\nlet data = $input.item.json;\n\n// 2. Get the existing columns from the Google Sheet (Read Node)\n// IMPORTANT: Ensure the name inside $('...') matches your Google Sheets Read node name exactly.\nconst sheetData = $('Get row(s) in sheet').item.json;\nconst originalDomain = sheetData.Domain; // Preserve the matching key\n\n// 3. Handle API Response Variations\n// The API might return an array [ {} ] or a single object {}.\nif (Array.isArray(data) && data.length > 0) {\n  data = data[0];\n}\n\n// 4. Flattening Function\n// Converts nested objects (e.g., location: { city: \"X\" }) -> location_city: \"X\"\n// Converts arrays (e.g., keywords: [\"a\", \"b\"]) -> keywords: \"a, b\"\nfunction flattenObject(obj, prefix = '') {\n  return Object.keys(obj).reduce((acc, k) => {\n    const pre = prefix.length ? prefix + '_' : '';\n    const val = obj[k];\n\n    // Handle null or undefined\n    if (val === null || val === undefined) {\n      acc[pre + k] = \"\";\n    }\n    // Handle Arrays: Join with comma\n    else if (Array.isArray(val)) {\n      acc[pre + k] = val.map(v => typeof v === 'object' ? JSON.stringify(v) : v).join(\", \");\n    }\n    // Handle Nested Objects: Recursive call (excluding Dates)\n    else if (typeof val === 'object' && !(val instanceof Date)) {\n      Object.assign(acc, flattenObject(val, pre + k));\n    }\n    // Handle Primitives (String, Number, Boolean)\n    else {\n      acc[pre + k] = val;\n    }\n    return acc;\n  }, {});\n}\n\n// Execute Flattening\nlet flatData = flattenObject(data);\n\n// 5. COLUMN FILTERING LOGIC\n// Only allow fields that actually exist as headers in the Google Sheet.\nconst allowedColumns = Object.keys(sheetData);\nlet filteredData = {};\n\n// Always include mandatory fields for the workflow logic\nfilteredData['Domain'] = originalDomain;\nfilteredData['Status'] = \"Done\";\nfilteredData['Last Updated'] = new Date().toISOString();\n\n// Loop through API data and pick only what is needed\nfor (const key of Object.keys(flatData)) {\n  // If the Google Sheet has this column, add it to the payload\n  if (allowedColumns.includes(key)) {\n    filteredData[key] = flatData[key];\n  }\n}\n\nreturn filteredData;"
      },
      "typeVersion": 2
    },
    {
      "id": "f1721f7b-8f22-4183-9142-6541745b3c53",
      "name": "Fetch Company Data",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        752,
        480
      ],
      "parameters": {
        "url": "https://api.companyenrich.com/companies/enrich",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "domain",
              "value": "={{ $json.Domain }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "cdd458c9-b469-45f5-9028-37aef18c5fca",
  "connections": {
    "Filter": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Update row in sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch Company Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Data Cleaning (JS)": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Company Data": {
      "main": [
        [
          {
            "node": "Data Cleaning (JS)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "Filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}