{
  "id": "9LpPrID2YPchvT3M",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Batch index Google Drive folder files into Google Sheets",
  "tags": [
    {
      "id": "ESdtU65Wllxq9nEk",
      "name": "auditing",
      "createdAt": "2026-03-19T14:31:37.415Z",
      "updatedAt": "2026-03-19T14:31:37.415Z"
    },
    {
      "id": "NqkO0R23De6nAXL7",
      "name": "indexing",
      "createdAt": "2026-04-28T17:40:23.258Z",
      "updatedAt": "2026-04-28T17:40:23.258Z"
    },
    {
      "id": "trgwQdeUrjGXXPp8",
      "name": "organization",
      "createdAt": "2026-04-28T17:40:30.431Z",
      "updatedAt": "2026-04-28T17:40:30.431Z"
    }
  ],
  "nodes": [
    {
      "id": "2824d89d-4d3d-44f1-8aab-7cb920d7bbd9",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        0,
        96
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "4660a1e0-f29b-4d48-b871-1ce151bb5edb",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "position": [
        224,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4ce71ee7-467d-4990-8d1e-aa0e0e641cac",
              "name": "targetFolderId",
              "type": "string",
              "value": "\"INPUT_FILE_ID_HERE\""
            },
            {
              "id": "96eca677-e0f4-4574-8f00-ec314cd6ef7f",
              "name": "indexSpreadsheetId",
              "type": "string",
              "value": "\"INPUT_GOOGLE_SPREADSHEET_ID_HERE\""
            },
            {
              "id": "2b1357f6-4082-468d-9acd-e930fdea8b56",
              "name": "indexSheetName",
              "type": "string",
              "value": "Sheet1 (OR_OTHER_SHEET_AS_APPROPRIATE)"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8979abe6-7651-47a2-b7c3-5917a88b061b",
      "name": "List files and folders",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        448,
        0
      ],
      "parameters": {
        "filter": {},
        "options": {
          "fields": [
            "id",
            "mimeType",
            "name",
            "webViewLink"
          ]
        },
        "resource": "fileFolder",
        "returnAll": true,
        "queryString": "={{ \"'\" + $json.targetFolderId + \"' in parents and trashed = false\" }}",
        "searchMethod": "query"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "68091f5d-60dd-4d1b-a50f-e8fe11e9f80d",
      "name": "Get Existing Index Rows",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        448,
        192
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": []
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Config').item.json.indexSheetName }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Config').item.json.indexSpreadsheetId }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "5efb9afe-76c5-49a3-bb45-cf4252c31eda",
      "name": "Filter Already Indexed Files",
      "type": "n8n-nodes-base.code",
      "position": [
        896,
        96
      ],
      "parameters": {
        "jsCode": "const existingRows = $('Get Existing Index Rows').all();\n\nconst existingIds = new Set(\n  existingRows\n    .map(row => row.json['File ID'])\n    .filter(Boolean)\n);\n\nreturn items.filter(item => !existingIds.has(item.json.id));"
      },
      "typeVersion": 2
    },
    {
      "id": "16df08cc-181d-458a-b4fb-b8ea3fc22803",
      "name": "Prepare Index Row",
      "type": "n8n-nodes-base.code",
      "position": [
        1120,
        96
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const file = item.json;\n\n  const extension = file.name && file.name.includes('.')\n    ? file.name.split('.').pop().toLowerCase()\n    : '';\n\n  return {\n    json: {\n      'File ID': file.id || '',\n      'File Name': file.name || '',\n      'MIME Type': file.mimeType || '',\n      'File Extension': extension,\n      'Google Drive URL': file.webViewLink || '',\n      'Indexed At': new Date().toISOString(),\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "1ecdc36f-a51b-494c-a956-07d41c6d8cc9",
      "name": "Append Row to Index Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1344,
        96
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "File Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "File Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "MIME Type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "MIME Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "File Extension",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "File Extension",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Google Drive URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Google Drive URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Indexed At",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Indexed At",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "File ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "File ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Config').item.json.indexSheetName }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Config').item.json.indexSpreadsheetId }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "a80b675b-94b6-4b6d-95c3-9e49107bae59",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        672,
        96
      ],
      "parameters": {
        "mode": "chooseBranch"
      },
      "typeVersion": 3.2
    },
    {
      "id": "2d48a86d-4a71-4886-8599-d98cc7ef1534",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -704,
        -288
      ],
      "parameters": {
        "color": "#F1FF2E",
        "width": 656,
        "height": 800,
        "content": "## How it works\n\n- On execution, the workflow reads a target Google Drive folder ID and destination spreadsheet from a single Config node \u2014 the only place you need to make changes.\n- Two branches run in parallel: one lists all files and folders inside the target Drive folder; the other reads any rows already present in the index spreadsheet.\n- A filter step compares the two lists by File ID, ensuring only new, previously unindexed files are processed \u2014 re-running the workflow will never create duplicates.\n- Each new file is formatted into a structured row containing: File Name, MIME Type, File Extension, Google Drive URL, File ID, and an ISO timestamp of when it was indexed.\n- New rows are appended to the specified sheet automatically.\n\n## Set-up Steps\n1. Connect your Google Drive and Google Sheets OAuth2 accounts in n8n credentials.\n2. Create a Google Sheet with the following column headers in row 1 (order does not matter): File Name, MIME Type, File Extension, Google Drive URL, File ID, Indexed At.\n3. Open the Config node and fill in three values: your target Google Drive folder ID, your Google Sheets spreadsheet ID, and the sheet tab name (defaults to Sheet1).\n4. Run the workflow manually to populate the index. Re-run anytime to append newly added files \u2014 existing entries are skipped automatically.\n\n## Requirements\n- Google Drive OAuth2 credentials (n8n built-in)\n- Google Sheets OAuth2 credentials (n8n built-in)\n- A Google Drive folder you want to index\n- A Google Sheet with the column headers listed above already in place\n\n## How to customize\n- Change what's captured: Edit the List files and folders node to request additional Drive file fields (e.g. createdTime, modifiedTime, owners), then add the corresponding columns to the Prepare Index Row code node.\n- Limit file volume: For folders with 50+ files, add an n8n Limit node between List files and folders and Merge to process in batches and avoid timeouts.\n- Schedule it: Swap the manual trigger for a Schedule trigger to keep your index automatically up to date on a recurring basis.\n- Filter by file type: Add an If or Filter node after List files and folders to only index specific MIME types (e.g. Google Docs only, PDFs only)."
      },
      "typeVersion": 1
    },
    {
      "id": "03a7a24d-09ba-4e2f-9a8d-f753f50a9ada",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        32
      ],
      "parameters": {
        "width": 368,
        "height": 224,
        "content": "## Start-up Phase"
      },
      "typeVersion": 1
    },
    {
      "id": "746eb927-f8d3-4b55-901b-1cf4451d4859",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        384,
        -96
      ],
      "parameters": {
        "width": 416,
        "height": 448,
        "content": "## Pulling Information from Google Drive and Google Sheets"
      },
      "typeVersion": 1
    },
    {
      "id": "29ed3ce1-f80f-4534-95af-3ce88bf9f46c",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        848,
        -32
      ],
      "parameters": {
        "width": 416,
        "height": 304,
        "content": "## Processing information pulled from Google Drive and Goggle Sheets"
      },
      "typeVersion": 1
    },
    {
      "id": "eb2b889c-18de-481b-af9a-507cd1454de3",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1296,
        -32
      ],
      "parameters": {
        "width": 192,
        "height": 304,
        "content": "## Adding data to Index Sheet"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "a8072480-0800-4752-ab84-cf7fbad28df2",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Filter Already Indexed Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "List files and folders",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Existing Index Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Index Row": {
      "main": [
        [
          {
            "node": "Append Row to Index Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List files and folders": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Existing Index Rows": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Filter Already Indexed Files": {
      "main": [
        [
          {
            "node": "Prepare Index Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}