{
  "name": "Competitor Research: BrightData SERP API to Google Sheets Automation",
  "nodes": [
    {
      "id": "b030f1ec-a894-4996-8af1-0bc94e0ce54c",
      "name": "When clicking 'Execute workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1080,
        20
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "2277478f-05ca-4cb0-8307-f6e7342c801f",
      "name": "Get Keywords from Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -800,
        20
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
          "cachedResultName": "Keywords"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "1b1f2e2c-d2e5-4ac4-9521-7ea9f82875bf",
      "name": "URL Encode Keywords",
      "type": "n8n-nodes-base.code",
      "position": [
        -520,
        20
      ],
      "parameters": {
        "jsCode": "const encode = encodeURIComponent; for (const item of $input.all()) { item.json.Keyword = encode(item.json.Keyword); } return $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "909de1db-a90d-475a-86a2-5ba9519820a5",
      "name": "Process Keywords in Batches",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -220,
        20
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "9584b867-e0d4-447b-9051-24cea36d7456",
      "name": "Fetch Google Search Results",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        100,
        40
      ],
      "parameters": {
        "url": "https://api.brightdata.com/request",
        "method": "POST",
        "options": {
          "redirect": {
            "redirect": {}
          }
        },
        "sendBody": true,
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "zone",
              "value": "serp_api1"
            },
            {
              "name": "url",
              "value": "=https://www.google.com/search?q={{ $json.Keyword }}"
            },
            {
              "name": "format",
              "value": "raw"
            },
            {
              "name": "country",
              "value": "= {{ $json['Target Country'] }}"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "async",
              "value": "true"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "51500526-1e34-4a13-be69-01dc2c97d23e",
      "name": "Extract Competitor Data from HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        380,
        40
      ],
      "parameters": {
        "jsCode": "const html = $input.first().json.data || ''; return [{json: {websiteName: 'demo', websiteUrl: 'https://example.com', websiteTitle: 'Example Title', websiteDescription: 'Example description'}}];"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "stickyNote:0",
      "name": "Workflow Start",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1080,
        120
      ],
      "parameters": {
        "content": "This workflow is triggered manually by clicking 'Execute workflow'.\n\nIt fetches keywords and target countries from a Google Sheet to perform SERP analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "stickyNote:1",
      "name": "Read Keywords",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -800,
        120
      ],
      "parameters": {
        "content": "Reads data from the specified Google Sheet.\n\nExpects columns like 'Keyword' and 'Target Country'.\n\n**Remember to replace 'YOUR_GOOGLE_SHEET_ID' and 'YOUR_GOOGLE_SHEETS_CREDENTIAL_ID'.**"
      },
      "typeVersion": 1
    },
    {
      "id": "stickyNote:2",
      "name": "Encode Keywords",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -520,
        120
      ],
      "parameters": {
        "content": "Encodes the 'Keyword' value using `encodeURIComponent`.\n\nThis is necessary to ensure keywords with special characters are correctly formatted for the URL."
      },
      "typeVersion": 1
    },
    {
      "id": "stickyNote:3",
      "name": "Batch Processing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -220,
        120
      ],
      "parameters": {
        "content": "Splits the list of keywords into smaller batches.\n\nThis helps manage the number of requests sent to the BrightData API at once, improving stability and handling potential rate limits."
      },
      "typeVersion": 1
    },
    {
      "id": "stickyNote:4",
      "name": "Fetch SERP Data",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        100,
        140
      ],
      "parameters": {
        "content": "Calls the BrightData SERP API to get search results for each keyword/country.\n\nUses the 'serp_api1' zone and constructs the Google search URL.\n\n**Remember to replace 'YOUR_BRIGHTDATA_CREDENTIAL_ID'.**"
      },
      "typeVersion": 1
    },
    {
      "id": "stickyNote:5",
      "name": "Extract Data (Placeholder)",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        380,
        140
      ],
      "parameters": {
        "content": "This node is intended to parse the HTML response from BrightData.\n\n**The current code is a placeholder.** You need to implement the logic to extract competitor websites, titles, descriptions, etc., from the HTML."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {},
  "connections": {
    "URL Encode Keywords": {
      "main": [
        [
          {
            "node": "Process Keywords in Batches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Keywords from Sheet": {
      "main": [
        [
          {
            "node": "URL Encode Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Google Search Results": {
      "main": [
        [
          {
            "node": "Extract Competitor Data from HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Keywords in Batches": {
      "main": [
        [
          {
            "node": "Fetch Google Search Results",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "When clicking 'Execute workflow'": {
      "main": [
        [
          {
            "node": "Get Keywords from Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}