This workflow follows the Google Sheets → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Keyword Research \u2014 Google Ads Keyword Metrics",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "30 0 * * *"
}
]
}
},
"id": "kw-1-schedule",
"name": "Schedule Trigger (00:30 AM)",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
240,
300
]
},
{
"parameters": {
"operation": "read",
"sheetId": {
"value": "={{ $env.SHEET_ID }}"
},
"range": "A:H",
"options": {
"filters": {
"column": "\uac80\uc0c9\ubcfc\ub968",
"value": ""
}
}
},
"id": "kw-2-sheets-read",
"name": "Sheets Read (\uac80\uc0c9\ubcfc\ub968 \ube44\uc5b4\uc788\ub294 \ud589)",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
460,
300
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "// batch_keywords.js \u2014 \ud0a4\uc6cc\ub4dc 10\uac1c\uc529 \ubc30\uce58 \ubd84\ud560\n// n8n/code_nodes/batch_keywords.js \ub0b4\uc6a9\uc744 \uc5ec\uae30\uc5d0 \ubcf5\uc0ac"
},
"id": "kw-3-batch",
"name": "Batch Keywords (10\uac1c\uc529)",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
680,
300
]
},
{
"parameters": {
"batchSize": 1,
"options": {}
},
"id": "kw-4-loop",
"name": "Loop Over Batches",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
900,
300
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// get_access_token.js \u2014 Service Account JWT \u2192 Access Token \uad50\ud658\n// n8n/code_nodes/get_access_token.js \ub0b4\uc6a9\uc744 \uc5ec\uae30\uc5d0 \ubcf5\uc0ac"
},
"id": "kw-5-auth",
"name": "Get Access Token (JWT)",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1120,
300
]
},
{
"parameters": {
"method": "POST",
"url": "=https://googleads.googleapis.com/v18/customers/{{ $env.GOOGLE_ADS_CUSTOMER_ID }}:generateKeywordIdeas",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $json.accessToken }}"
},
{
"name": "developer-token",
"value": "={{ $env.GOOGLE_ADS_DEVELOPER_TOKEN }}"
},
{
"name": "login-customer-id",
"value": "={{ $env.GOOGLE_ADS_LOGIN_CUSTOMER_ID }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"language\": \"languageConstants/1023\",\n \"geoTargetConstants\": [\"geoTargetConstants/2410\"],\n \"keywordPlanNetwork\": \"GOOGLE_SEARCH\",\n \"keywordSeed\": {\n \"keywords\": {{ JSON.stringify($json.keywords) }}\n }\n}",
"options": {
"response": {
"response": {
"fullResponse": true
}
},
"timeout": 30000
}
},
"id": "kw-6-google-ads",
"name": "Google Ads generateKeywordIdeas",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1340,
300
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// parse_keyword_metrics.js \u2014 Google Ads \uc751\ub2f5 \u2192 \ubcfc\ub968/CPC/\ub09c\uc774\ub3c4/\uc6b0\uc120\uc21c\uc704 \ubcc0\ud658\n// n8n/code_nodes/parse_keyword_metrics.js \ub0b4\uc6a9\uc744 \uc5ec\uae30\uc5d0 \ubcf5\uc0ac"
},
"id": "kw-7-parse",
"name": "Parse Keyword Metrics",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1560,
300
]
},
{
"parameters": {
"operation": "update",
"sheetId": {
"value": "={{ $env.SHEET_ID }}"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"\uac80\uc0c9\ubcfc\ub968": "={{ $json.\uac80\uc0c9\ubcfc\ub968 }}",
"\uc608\uc0c1CPC": "={{ $json.\uc608\uc0c1CPC }}",
"\ub09c\uc774\ub3c4": "={{ $json.\ub09c\uc774\ub3c4 }}",
"\uc6b0\uc120\uc21c\uc704": "={{ $json.\uc6b0\uc120\uc21c\uc704 }}"
},
"matchingColumns": [
"\ud0a4\uc6cc\ub4dc"
]
}
},
"id": "kw-8-sheets-update",
"name": "Sheets Update (\uba54\ud2b8\ub9ad \uae30\ub85d)",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
1780,
300
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"amount": 1.5,
"unit": "seconds"
},
"id": "kw-9-wait",
"name": "Wait 1.5s (Rate Limit)",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
2000,
300
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Error Handler \u2014 API \uc5d0\ub7ec \uc2dc \uae30\ubcf8\uac12\uc73c\ub85c graceful degradation\nconst batchData = $('Loop Over Batches').item.json;\nconst keywords = batchData.keywords || [];\nconst rowNumbers = batchData.rowNumbers || [];\nconst output = [];\n\nfor (let i = 0; i < keywords.length; i++) {\n output.push({\n json: {\n \ud0a4\uc6cc\ub4dc: keywords[i],\n rowNumber: rowNumbers[i] || '',\n \uac80\uc0c9\ubcfc\ub968: 0,\n \uc608\uc0c1CPC: 0,\n \ub09c\uc774\ub3c4: 20,\n \uc6b0\uc120\uc21c\uc704: 'C',\n }\n });\n}\n\nreturn output;"
},
"id": "kw-err-handler",
"name": "Error Handler (Graceful Degradation)",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1560,
500
]
},
{
"parameters": {
"operation": "update",
"sheetId": {
"value": "={{ $env.SHEET_ID }}"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"\uac80\uc0c9\ubcfc\ub968": "={{ $json.\uac80\uc0c9\ubcfc\ub968 }}",
"\uc608\uc0c1CPC": "={{ $json.\uc608\uc0c1CPC }}",
"\ub09c\uc774\ub3c4": "={{ $json.\ub09c\uc774\ub3c4 }}",
"\uc6b0\uc120\uc21c\uc704": "={{ $json.\uc6b0\uc120\uc21c\uc704 }}"
},
"matchingColumns": [
"\ud0a4\uc6cc\ub4dc"
]
}
},
"id": "kw-err-sheets-update",
"name": "Sheets Update (\uc5d0\ub7ec \uae30\ubcf8\uac12)",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
1780,
500
],
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Schedule Trigger (00:30 AM)": {
"main": [
[
{
"node": "Sheets Read (\uac80\uc0c9\ubcfc\ub968 \ube44\uc5b4\uc788\ub294 \ud589)",
"type": "main",
"index": 0
}
]
]
},
"Sheets Read (\uac80\uc0c9\ubcfc\ub968 \ube44\uc5b4\uc788\ub294 \ud589)": {
"main": [
[
{
"node": "Batch Keywords (10\uac1c\uc529)",
"type": "main",
"index": 0
}
]
]
},
"Batch Keywords (10\uac1c\uc529)": {
"main": [
[
{
"node": "Loop Over Batches",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Batches": {
"main": [
[
{
"node": "Get Access Token (JWT)",
"type": "main",
"index": 0
}
],
[]
]
},
"Get Access Token (JWT)": {
"main": [
[
{
"node": "Google Ads generateKeywordIdeas",
"type": "main",
"index": 0
}
]
]
},
"Google Ads generateKeywordIdeas": {
"main": [
[
{
"node": "Parse Keyword Metrics",
"type": "main",
"index": 0
}
],
[
{
"node": "Error Handler (Graceful Degradation)",
"type": "main",
"index": 0
}
]
]
},
"Parse Keyword Metrics": {
"main": [
[
{
"node": "Sheets Update (\uba54\ud2b8\ub9ad \uae30\ub85d)",
"type": "main",
"index": 0
}
]
]
},
"Sheets Update (\uba54\ud2b8\ub9ad \uae30\ub85d)": {
"main": [
[
{
"node": "Wait 1.5s (Rate Limit)",
"type": "main",
"index": 0
}
]
]
},
"Wait 1.5s (Rate Limit)": {
"main": [
[
{
"node": "Loop Over Batches",
"type": "main",
"index": 0
}
]
]
},
"Error Handler (Graceful Degradation)": {
"main": [
[
{
"node": "Sheets Update (\uc5d0\ub7ec \uae30\ubcf8\uac12)",
"type": "main",
"index": 0
}
]
]
},
"Sheets Update (\uc5d0\ub7ec \uae30\ubcf8\uac12)": {
"main": [
[
{
"node": "Wait 1.5s (Rate Limit)",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"timezone": "Asia/Seoul",
"saveManualExecutions": true
},
"meta": {
"templateId": "",
"notes": "Pipeline A \ubcf4\uc870 \uc6cc\ud06c\ud50c\ub85c\uc6b0: Google Ads Keyword Planner API\ub85c \ud0a4\uc6cc\ub4dc \uba54\ud2b8\ub9ad \uc0ac\uc804 \uc218\uc9d1.\n\ub9e4\uc77c 00:30\uc5d0 \uc2e4\ud589, Pipeline A(01:00)\ubcf4\ub2e4 30\ubd84 \uba3c\uc800.\n\uac80\uc0c9\ubcfc\ub968\uc774 \ube44\uc5b4\uc788\ub294 \ud589\ub9cc \ub300\uc0c1.\n\uc5d0\ub7ec \uc2dc \uae30\ubcf8\uac12 \uc720\uc9c0 (graceful degradation)."
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Keyword Research — Google Ads Keyword Metrics. Uses googleSheets, httpRequest. Scheduled trigger; 11 nodes.
Source: https://github.com/KIMSANGHYEON93/blog-automation/blob/eb116e8781b2080ef82ac6010eda6aa366da7b0a/n8n/workflow_keyword_research.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow automates video distribution to 9 social platforms simultaneously using Blotato's API. It includes both a scheduled publisher (checks Google Sheets for videos marked "Ready") and a subwo
YogiAI. Uses googleSheets, googleSheetsTool, httpRequest, stopAndError. Scheduled trigger; 61 nodes.
This workflow monitors Google Calendar for events indicating that a customer will visit the company today or the next day, retrieves the required details, and sends reminder notifications to the relev
ofn hook v0.24.0 beta. Uses start, httpRequest, functionItem, itemLists. Scheduled trigger; 42 nodes.
Security teams, DevOps engineers, vulnerability analysts, and automation builders who want to eliminate repetitive Nessus scan parsing, AI-based risk triage, and manual reporting. Designed for orgs fo