{
  "version": "1.0",
  "title": "Scrape.do - Bulk URL Scraper",
  "description": "Reads a list of URLs from Google Sheets, scrapes each one through the Scrape.do API, parses the response, and writes structured rows back to a results sheet.",
  "configData": [
    {
      "key": "scrape_do_token",
      "description": "Scrape.do API token from dashboard.scrape.do",
      "value": ""
    },
    {
      "key": "source_sheet_id",
      "description": "Google Sheets ID holding the URL list",
      "value": ""
    },
    {
      "key": "results_sheet_id",
      "description": "Google Sheets ID for scraped results",
      "value": ""
    }
  ],
  "requiredAuthentications": [
    {
      "service": "google-sheets",
      "label": "Google Sheets",
      "note": "Select or create this authentication during import."
    }
  ],
  "workflow": {
    "triggerType": "manual",
    "steps": [
      {
        "id": "trigger",
        "name": "Manual Trigger",
        "connector": { "name": "manual", "version": "1.0" },
        "operation": "manual",
        "position": { "x": 0, "y": 0 },
        "input": {}
      },
      {
        "id": "google-sheets-1",
        "name": "Get URL list",
        "connector": { "name": "google-sheets", "version": "7.0" },
        "operation": "get_rows",
        "position": { "x": 0, "y": 160 },
        "input": {
          "spreadsheet_id": { "type": "JSONPATH", "value": "$.config.source_sheet_id" },
          "worksheet_name": { "type": "STRING", "value": "Sheet1" },
          "has_headers": { "type": "BOOLEAN", "value": true }
        }
      },
      {
        "id": "loop-1",
        "name": "Loop over URLs",
        "connector": { "name": "loop", "version": "2.0" },
        "operation": "loop_list",
        "position": { "x": 0, "y": 320 },
        "input": {
          "list": { "type": "JSONPATH", "value": "$.steps.google-sheets-1.rows" },
          "parallel": { "type": "BOOLEAN", "value": true },
          "concurrency": { "type": "NUMBER", "value": 5 }
        },
        "children": ["http-client-1", "script-1", "google-sheets-2"]
      },
      {
        "id": "http-client-1",
        "name": "Scrape.do request",
        "connector": { "name": "http-client", "version": "4.0" },
        "operation": "get",
        "parent": "loop-1",
        "position": { "x": 200, "y": 420 },
        "input": {
          "url": { "type": "STRING", "value": "https://api.scrape.do/" },
          "method": { "type": "STRING", "value": "GET" },
          "query_parameters": {
            "type": "OBJECT",
            "value": [
              { "key": "token",   "value": { "type": "JSONPATH", "value": "$.config.scrape_do_token" } },
              { "key": "url",     "value": { "type": "JSONPATH", "value": "$.steps.loop-1.value.url" } },
              { "key": "output",  "value": { "type": "STRING", "value": "raw" } },
              { "key": "render",  "value": { "type": "STRING", "value": "false" } },
              { "key": "super",   "value": { "type": "STRING", "value": "false" } },
              { "key": "geoCode", "value": { "type": "STRING", "value": "us" } }
            ]
          },
          "parse_response": { "type": "BOOLEAN", "value": false },
          "timeout": { "type": "NUMBER", "value": 120000 }
        },
        "errorHandling": {
          "onError": "continue",
          "retryCount": 2,
          "retryDelayMs": 1000
        }
      },
      {
        "id": "script-1",
        "name": "Normalize result",
        "connector": { "name": "script", "version": "3.0" },
        "operation": "execute_script",
        "parent": "loop-1",
        "position": { "x": 200, "y": 560 },
        "input": {
          "variables": {
            "type": "OBJECT",
            "value": [
              { "key": "source_url", "value": { "type": "JSONPATH", "value": "$.steps.loop-1.value.url" } },
              { "key": "response",   "value": { "type": "JSONPATH", "value": "$.steps.http-client-1.response.body" } },
              { "key": "status",     "value": { "type": "JSONPATH", "value": "$.steps.http-client-1.response.status_code" } }
            ]
          },
          "script": {
            "type": "STRING",
            "value": "exports.step = function(input) {\n  const body = input.response || '';\n  const ok = input.status === 200 && body.length > 0;\n\n  const pick = (re) => {\n    const m = ok ? body.match(re) : null;\n    return m ? m[1].replace(/\\s+/g, ' ').trim() : '';\n  };\n\n  return {\n    url: input.source_url,\n    name: pick(/<span id=\"productTitle\"[^>]*>([\\s\\S]*?)<\\/span>/),\n    asin: pick(/\"asin\":\"([A-Z0-9]{10})\"/),\n    price: pick(/<span class=\"a-offscreen\">\\$([0-9.,]+)<\\/span>/),\n    rating: pick(/(\\d+\\.?\\d*)\\s*out of/),\n    status: ok ? 'ok' : 'failed',\n    scraped_at: new Date().toISOString()\n  };\n};"
          }
        }
      },
      {
        "id": "google-sheets-2",
        "name": "Append result row",
        "connector": { "name": "google-sheets", "version": "7.0" },
        "operation": "add_row",
        "parent": "loop-1",
        "position": { "x": 200, "y": 700 },
        "input": {
          "spreadsheet_id": { "type": "JSONPATH", "value": "$.config.results_sheet_id" },
          "worksheet_name": { "type": "STRING", "value": "Sheet1" },
          "values": {
            "type": "OBJECT",
            "value": [
              { "key": "URL",     "value": { "type": "JSONPATH", "value": "$.steps.script-1.result.url" } },
              { "key": "ASIN",    "value": { "type": "JSONPATH", "value": "$.steps.script-1.result.asin" } },
              { "key": "Name",    "value": { "type": "JSONPATH", "value": "$.steps.script-1.result.name" } },
              { "key": "Price",   "value": { "type": "JSONPATH", "value": "$.steps.script-1.result.price" } },
              { "key": "Rating",  "value": { "type": "JSONPATH", "value": "$.steps.script-1.result.rating" } },
              { "key": "Status",  "value": { "type": "JSONPATH", "value": "$.steps.script-1.result.status" } },
              { "key": "Scraped", "value": { "type": "JSONPATH", "value": "$.steps.script-1.result.scraped_at" } }
            ]
          }
        }
      }
    ]
  }
}
