8
n8n 한국어amn8n.com

BrightData 주간 비교

고급

이것은AI, Marketing분야의자동화 워크플로우로, 35개의 노드를 포함합니다.주로 If, Set, Code, Gmail, Markdown 등의 노드를 사용하며인공지능 기술을 결합하여 스마트 자동화를 구현합니다. Bright Data, GPT-4.1, Google Workspace를 활용한 자동화 웹사이트 변경 모니터링

사전 요구사항
  • Google 계정 및 Gmail API 인증 정보
  • Google Drive API 인증 정보
  • Google Sheets API 인증 정보
  • OpenAI API Key
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "id": "pNaD8QIgVGDqbCoU",
  "meta": {
    "instanceId": "3af183a3db355380be4f6d2f3dfb18bdaa750e90f99a48f91bd71080ee6bcbe8",
    "templateCredsSetupCompleted": true
  },
  "name": "BrightData Weekly Comparison",
  "tags": [],
  "nodes": [
    {
      "id": "a2966ed3-e998-47ca-83b3-b7dc4832bc8f",
      "name": "구조화된 출력 파서",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        700,
        140
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"filename\": \"domain-path-DD-MM-YYYY.md\",\n  \"metadata\": {\n    \"pageTitle\": \"The primary title of the webpage\",\n    \"metaDescription\": \"The meta description content\"\n  },\n  \"headings\": {\n    \"h1\": [\"List of all H1 headings\"],\n    \"h2\": [\"List of all H2 headings\"],\n    \"h3\": [\"List of all H3 headings\"]\n  },\n  \"pricing\": [\n    {\n      \"planName\": \"Name of the pricing plan/tier\",\n      \"currency\": \"USD/EUR/GBP/etc.\",\n      \"interval\": \"monthly/yearly/one-time\",\n      \"price\": \"Numerical price value\",\n      \"features\": [\"List of features or benefits included in this plan\"]\n    }\n  ],\n  \"navigation\": {\n    \"mainMenu\": [\"Primary navigation items\"],\n    \"subMenu\": [\"Secondary navigation items if present\"]\n  },\n  \"callToAction\": [\"All CTA elements and their text\"],\n  \"contactInfo\": {\n    \"phone\": [\"Phone numbers found\"],\n    \"email\": [\"Email addresses found\"],\n    \"address\": [\"Physical addresses found\"],\n    \"formPresent\": true\n  },\n  \"banners\": [\"Content from promotional banners\"],\n  \"faq\": [\n    {\n      \"question\": \"FAQ question\",\n      \"answer\": \"FAQ answer\"\n    }\n  ]\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "6d4b38bd-fb58-4675-9b83-ade043914d65",
      "name": "워크플로 변수 설정",
      "type": "n8n-nodes-base.set",
      "position": [
        -260,
        -120
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "96347cce-576a-413c-9c9b-b2257eced54d",
              "name": "DriveFolderID",
              "type": "string",
              "value": ""
            },
            {
              "id": "b2f5e75f-575d-40ed-89a8-1c2e537d3220",
              "name": "ComparisonSpreadsheetID",
              "type": "string",
              "value": ""
            },
            {
              "id": "f64718d6-a5f2-491e-abec-b26a6e6125e8",
              "name": "ComparisonSpreadsheetSheetName",
              "type": "string",
              "value": "Sheet1"
            },
            {
              "id": "1a71595c-58c3-4eda-9b7b-5c306123db86",
              "name": "Email",
              "type": "string",
              "value": ""
            },
            {
              "id": "ed5fe6bd-b43b-45b1-b1e8-b20beb329e4d",
              "name": "IsTest",
              "type": "boolean",
              "value": false
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "6ddda34f-556e-49a5-a103-7641a3f0598d",
      "name": "Google 시트 데이터와 워크플로 변수 병합",
      "type": "n8n-nodes-base.set",
      "position": [
        180,
        -120
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e129ca16-8675-485e-9f21-e5d22b76c6e6",
              "name": "ComparisonSpreadsheetFileName",
              "type": "string",
              "value": "={{ $('Set workflow variables').item.json.ComparisonSpreadsheetFileName }}"
            },
            {
              "id": "5fdee148-82eb-4542-9fe7-1ba37ec09571",
              "name": "ComparisonSpreadsheetSheetName",
              "type": "string",
              "value": "={{ $('Set workflow variables').item.json.ComparisonSpreadsheetSheetName }}"
            },
            {
              "id": "7cce5924-a67a-45a2-8792-cd9ad28834b8",
              "name": "Email",
              "type": "string",
              "value": "={{ $('Set workflow variables').item.json.Email }}"
            },
            {
              "id": "e445b570-384f-4558-99d3-12802b0fa900",
              "name": "DriveFolderID",
              "type": "string",
              "value": "={{ $('Set workflow variables').item.json.DriveFolderID }}"
            },
            {
              "id": "d487666e-4dd3-4d20-8769-d0daf3bab268",
              "name": "IsTest",
              "type": "boolean",
              "value": "={{ $('Set workflow variables').item.json.IsTest }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "45eefb28-dce0-4fc3-81a1-865762c73226",
      "name": "비교 스프레드시트에서 읽기",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -40,
        -120
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.ComparisonSpreadsheetSheetName }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.ComparisonSpreadsheetID }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "vnXMSwscCP06bp9u",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "c04cec36-1664-48d7-a9ae-a5665bc2c188",
      "name": "각 비교 URL 순환 처리",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        400,
        -115
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "c50e3ec4-c3bf-4417-94ad-5b57ad6424da",
      "name": "웹 스크래핑 및 데이터 추출 에이전트",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        652,
        -365
      ],
      "parameters": {
        "text": "=Please scrape the following url {{ $json.URL }}\n",
        "options": {
          "systemMessage": "=## Role\nYou are an expert Web Data Extraction Specialist with a specialization in content analysis, information architecture, and structured data organization.\n\n## Task\nYour primary task is to extract, organize, and present key website components from any URL provided by the user.\nTo achieve this, you will need to perform the following:\n- Scrape the target webpage using the scrape_as_markdown tool to obtain its content\n- Generate a clean filename based on the URL and current date for storing the content as JSON\n- Systematically extract and categorize the following elements from the markdown content\n- Format the extracted data into a structured JSON object containing the processed elements\n\n## Tools\nYou can use the following tools:\n1. **scrape_as_markdown**: Use this tool to extract the full content of a webpage in Markdown format. This tool can bypass bot detection and CAPTCHA systems to ensure reliable extraction.\n\n## Input\nYou will receive input as a URL to the webpage that requires data extraction.\n\n## Output\nYour output must be a single, valid JSON object containing all extracted elements and a clean filename. Do not include any explanatory text before or after the JSON.\n\n{\n  \"filename\": \"domain-path-DD-MM-YYYY.json\",\n  \"metadata\": {\n    \"pageTitle\": \"The primary title of the webpage\",\n    \"metaDescription\": \"The meta description content\"\n  },\n  \"headings\": {\n    \"h1\": [\"List of all H1 headings\"],\n    \"h2\": [\"List of all H2 headings\"],\n    \"h3\": [\"List of all H3 headings\"]\n  },\n  \"pricing\": [\n    {\n      \"planName\": \"Name of the pricing plan/tier\",\n      \"currency\": \"USD/EUR/GBP/etc.\",\n      \"interval\": \"monthly/yearly/one-time\",\n      \"price\": \"Numerical price value\",\n      \"features\": [\"List of features or benefits included in this plan\"]\n    }\n  ],\n  \"navigation\": {\n    \"mainMenu\": [\"Primary navigation items\"],\n    \"subMenu\": [\"Secondary navigation items if present\"]\n  },\n  \"callToAction\": [\"All CTA elements and their text\"],\n  \"contactInfo\": {\n    \"phone\": [\"Phone numbers found\"],\n    \"email\": [\"Email addresses found\"],\n    \"address\": [\"Physical addresses found\"],\n    \"formPresent\": true/false\n  },\n  \"banners\": [\"Content from promotional banners\"],\n  \"faq\": [\n    {\n      \"question\": \"FAQ question\",\n      \"answer\": \"FAQ answer\"\n    }\n  ]\n}\n\nFor any elements not found on the webpage, include an empty array [] or appropriate null value. Ensure the JSON is properly formatted and valid. If the extraction process encounters any errors, include an additional \"errors\" key with relevant details.\n\nWhen extracting pricing information, analyze the webpage carefully to identify all pricing plans. For each plan, determine:\n- The name of the plan (e.g., \"Basic\", \"Pro\", \"Enterprise\")\n- The currency symbol or code used\n- Whether the pricing is monthly, yearly, or one-time\n- The numerical price value\n- All features or details associated with that pricing tier\n\nThe filename should be generated using the following format:\n- Extract the domain name from the URL (without www.)\n- Extract the path (without any query parameters or fragments)\n- Replace slashes with hyphens\n- Add the current date in DD-MM-YYYY format\n- Use .json as the file extension\n- For example, if the URL is https://asana.com/pricing and today is May 20, 2025, the filename would be \"asana-pricing-20-05-2025.json\"\n- Today's date is {{ $now }}\n\nEven if some pricing information is ambiguous or incomplete, make reasonable inferences and include all relevant details in the structured format."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "c1f69dc5-6612-4575-aaf4-1d6a7a70c423",
      "name": "금주 JSON 파일 업로드",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1280,
        -365
      ],
      "parameters": {
        "name": "={{ $('Web scraping and data extraction agent').item.json.output.filename }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Loop over each comparison URL').item.json.DriveFolderID }}"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "ENsCK6J7JBSny3Pv",
          "name": "Google Drive account"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "e4a1fd2c-e1a5-4065-a9c8-76d1c854af95",
      "name": "비교 시트에 금주 파일 데이터 업데이트",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1500,
        -365
      ],
      "parameters": {
        "columns": {
          "value": {
            "URL": "={{ $('Loop over each comparison URL').item.json.URL }}",
            "Previous Week ID": "={{ $('Loop over each comparison URL').item.json[\"Current Week File ID\"] }}",
            "Current Week File ID": "={{ $json.id }}",
            "Current Week File Link": "={{ $json.webViewLink }}",
            "Previous Week File Link": "={{ $('Loop over each comparison URL').item.json[\"Current Week File Link\"] }}"
          },
          "schema": [
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Previous Week ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Previous Week ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Previous Week File Link",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Previous Week File Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Current Week File ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Current Week File ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Current Week File Link",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Current Week File Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Comparison File",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Comparison File",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "URL"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1e4oheZjmxb3P7OXGY0uLWZKz2ENcp7XlEpIloOtRHEk/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1e4oheZjmxb3P7OXGY0uLWZKz2ENcp7XlEpIloOtRHEk",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1e4oheZjmxb3P7OXGY0uLWZKz2ENcp7XlEpIloOtRHEk/edit?usp=drivesdk",
          "cachedResultName": "BrightData Scraping Comparison"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "vnXMSwscCP06bp9u",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "32934604-9e72-4f6a-aa55-fc0abff1d85c",
      "name": "전주 파일 존재 여부 확인",
      "type": "n8n-nodes-base.if",
      "position": [
        1720,
        -365
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "d46019c6-ec3b-4e8b-80b2-44ffb2a82e51",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json[\"Previous Week ID\"] }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "301dfc46-f1d4-4b1a-892b-25ecb4495b77",
      "name": "전주 파일 다운로드",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1940,
        -365
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json[\"Previous Week ID\"] }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "ENsCK6J7JBSny3Pv",
          "name": "Google Drive account"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "036d00c9-7414-4883-ac56-ef9368195b85",
      "name": "전주 파일을 JSON 형식으로 변환",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        2160,
        -365
      ],
      "parameters": {
        "options": {},
        "operation": "fromJson"
      },
      "typeVersion": 1
    },
    {
      "id": "67b8ee0a-2ab0-43cd-b24f-0c8ba6b04cd1",
      "name": "전주 및 금주 설정",
      "type": "n8n-nodes-base.set",
      "position": [
        2380,
        -365
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "af75985e-4f86-4493-9fbd-0d0c7b383001",
              "name": "previous",
              "type": "object",
              "value": "={{ $json.data[0].output }}"
            },
            {
              "id": "718aeb81-59e9-49f9-aa5b-dc3c194d2efa",
              "name": "current",
              "type": "object",
              "value": "={{ $('Web scraping and data extraction agent').item.json.output }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "40b828f7-08f2-41ea-a6f7-595c5e4ae3e0",
      "name": "테스트 모드 확인",
      "type": "n8n-nodes-base.if",
      "position": [
        2600,
        -365
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "650a5f5e-3041-4d2f-a891-1d369b09c17a",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $('Loop over each comparison URL').item.json.IsTest }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "af562b9f-3cfc-4715-ae47-779a0554e7d2",
      "name": "전주 변경사항 모의 생성",
      "type": "n8n-nodes-base.code",
      "position": [
        2820,
        -440
      ],
      "parameters": {
        "jsCode": "// Code node in N8n\nconst inputData = $input.first().json;\n\n// Clone the previous data before modifying it\nconst previous = {...inputData.previous};\n\n// Change 1: Increase all numeric prices by $5 in the pricing array\nif (previous?.pricing && Array.isArray(previous.pricing)) {\n  previous.pricing.forEach(plan => {\n    // Check if price is a numeric string\n    if (plan.price && !isNaN(parseFloat(plan.price))) {\n      // Add $5 to the price\n      plan.price = (parseFloat(plan.price) + 5).toString();\n    }\n  });\n}\n\n// Change 2: Modify a feature in the first paid plan (if exists)\nif (previous?.pricing && previous.pricing.length > 1) {\n  const firstPaidPlan = previous.pricing.find(plan => \n    plan.price && plan.price !== \"0\" && !isNaN(parseFloat(plan.price)));\n  \n  if (firstPaidPlan && Array.isArray(firstPaidPlan.features) && firstPaidPlan.features.length > 1) {\n    // Add \"Premium\" prefix to the second feature (if it exists)\n    if (firstPaidPlan.features[1]) {\n      firstPaidPlan.features[1] = \"Premium \" + firstPaidPlan.features[1];\n    }\n  }\n}\n\n// Change 3: Update the first FAQ answer (if exists)\nif (previous?.faq && Array.isArray(previous.faq) && previous.faq.length > 0) {\n  if (previous.faq[0] && previous.faq[0].answer) {\n    // Add a sentence to the end of the answer\n    previous.faq[0].answer += \" For more information, contact our sales team.\";\n  }\n}\n\n// Return the data with current and modified previous\nreturn [{\n  json: {\n    current: inputData.current,\n    previous: previous\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "dd764b6d-d412-44e6-8816-e7b66bbb44c6",
      "name": "주간 변경사항 감지",
      "type": "n8n-nodes-base.code",
      "position": [
        3040,
        -365
      ],
      "parameters": {
        "jsCode": "// N8n Code Node to compare previous and current data\n// Input: $input.first().json contains previous and current data objects\n\nfunction detectChanges() {\n  const previous = $input.first().json.previous;\n  const current = $input.first().json.current;\n  \n  // Initialize changes object with better structure for Markdown generation\n  const changes = {\n    detected: false,\n    sections: {}, // Organized by section\n    summary: {\n      totalChanges: 0,\n      timestamp: new Date().toISOString()\n    }\n  };\n  \n  // Helper function to add a change to the changes object\n  function addChange(section, path, changeType, changeData) {\n    // Initialize section if it doesn't exist\n    if (!changes.sections[section]) {\n      changes.sections[section] = {\n        name: formatSectionName(section),\n        changes: []\n      };\n    }\n    \n    // Format display path\n    const displayPath = formatPath(path);\n    \n    // Add change to the section\n    changes.sections[section].changes.push({\n      displayPath,\n      type: changeType,\n      ...changeData\n    });\n    \n    // Update global detected flag and counter\n    changes.detected = true;\n    changes.summary.totalChanges++;\n  }\n  \n  // Helper function to format section name for display\n  function formatSectionName(name) {\n    // Convert camelCase to Title Case with spaces\n    return name.replace(/([A-Z])/g, ' $1')\n      .replace(/^./, str => str.toUpperCase())\n      .trim();\n  }\n  \n  // Helper function to format path for display\n  function formatPath(path) {\n    // Format the path elements to be more readable\n    return path.replace(/\\[([^\\]]+)\\]/g, ' ($1)');\n  }\n  \n  // Helper function to compare primitive values\n  function compareValues(prevVal, currVal, path) {\n    if (prevVal !== currVal) {\n      const section = path.split('.')[0];\n      addChange(section, path, 'changed', {\n        old: prevVal,\n        new: currVal\n      });\n      return true;\n    }\n    return false;\n  }\n  \n  // Helper function to compare arrays\n  function compareArrays(prevArr, currArr, path, matchKey = null) {\n    let changed = false;\n    const section = path.split('.')[0];\n    const additions = [];\n    const deletions = [];\n    \n    // Check for deletions\n    for (let i = 0; i < prevArr.length; i++) {\n      const prevItem = prevArr[i];\n      \n      if (matchKey && typeof prevItem === 'object' && prevItem !== null) {\n        // For arrays of objects with a specified match key (like planName or question)\n        const matchFound = currArr.some(currItem => currItem[matchKey] === prevItem[matchKey]);\n        if (!matchFound) {\n          deletions.push(prevItem);\n          changed = true;\n        }\n      } else {\n        // For arrays of primitives\n        if (!currArr.includes(prevItem)) {\n          deletions.push(prevItem);\n          changed = true;\n        }\n      }\n    }\n    \n    // Check for additions\n    for (let i = 0; i < currArr.length; i++) {\n      const currItem = currArr[i];\n      \n      if (matchKey && typeof currItem === 'object' && currItem !== null) {\n        // For arrays of objects with a specified match key\n        const matchFound = prevArr.some(prevItem => prevItem[matchKey] === currItem[matchKey]);\n        if (!matchFound) {\n          additions.push(currItem);\n          changed = true;\n        }\n      } else {\n        // For arrays of primitives\n        if (!prevArr.includes(currItem)) {\n          additions.push(currItem);\n          changed = true;\n        }\n      }\n    }\n    \n    // Check for changes in matching objects\n    if (matchKey) {\n      for (let i = 0; i < currArr.length; i++) {\n        const currItem = currArr[i];\n        if (typeof currItem === 'object' && currItem !== null) {\n          const matchingPrevItem = prevArr.find(prevItem => prevItem[matchKey] === currItem[matchKey]);\n          if (matchingPrevItem) {\n            // Compare the matching objects recursively\n            const itemPath = `${path}[${matchKey}=${currItem[matchKey]}]`;\n            compareObjects(matchingPrevItem, currItem, itemPath);\n          }\n        }\n      }\n    }\n    \n    if (changed) {\n      addChange(section, path, 'array_changed', {\n        additions: additions.length > 0 ? additions : null,\n        deletions: deletions.length > 0 ? deletions : null\n      });\n    }\n    \n    return changed;\n  }\n  \n  // Helper function to compare objects\n  function compareObjects(prevObj, currObj, path = '') {\n    if (!prevObj || !currObj) return false;\n    \n    const allKeys = new Set([...Object.keys(prevObj), ...Object.keys(currObj)]);\n    let changed = false;\n    \n    for (const key of allKeys) {\n      // Skip rawMarkdown as requested\n      if (key === 'rawMarkdown') continue;\n      \n      const keyPath = path ? `${path}.${key}` : key;\n      const section = keyPath.split('.')[0];\n      const prevVal = prevObj[key];\n      const currVal = currObj[key];\n      \n      // Handle missing keys\n      if (!(key in prevObj)) {\n        addChange(section, keyPath, 'added', {\n          value: currVal\n        });\n        changed = true;\n        continue;\n      }\n      \n      if (!(key in currObj)) {\n        addChange(section, keyPath, 'removed', {\n          value: prevVal\n        });\n        changed = true;\n        continue;\n      }\n      \n      // Compare based on type\n      if (Array.isArray(prevVal) && Array.isArray(currVal)) {\n        // Special handling for specific array types\n        if (key === 'pricing') {\n          compareArrays(prevVal, currVal, keyPath, 'planName');\n        } else if (key === 'features') {\n          compareArrays(prevVal, currVal, keyPath);\n        } else if (key === 'faq') {\n          compareArrays(prevVal, currVal, keyPath, 'question');\n        } else {\n          compareArrays(prevVal, currVal, keyPath);\n        }\n      } else if (\n        typeof prevVal === 'object' && prevVal !== null &&\n        typeof currVal === 'object' && currVal !== null\n      ) {\n        compareObjects(prevVal, currVal, keyPath);\n      } else {\n        compareValues(prevVal, currVal, keyPath);\n      }\n    }\n    \n    return changed;\n  }\n  \n  // Start comparison - removed the .output reference\n  compareObjects(previous, current);\n  \n  return [{ json: {previous, current, changes} }];\n}\n\n// Execute the function and return the results\nreturn detectChanges();"
      },
      "typeVersion": 2
    },
    {
      "id": "e5a8b7c1-53ec-4a26-8791-30db494cde92",
      "name": "감지된 변경사항을 마크다운으로 생성",
      "type": "n8n-nodes-base.code",
      "position": [
        3260,
        -365
      ],
      "parameters": {
        "jsCode": "// N8n Code Node to generate Markdown from structured changes\n// Input: $input.changes contains the comparison results from the improved comparison node\nfunction generateChangelogMarkdown() {\n  // Changed to directly access the changes property from the input\n  const changes = $input.first().json.changes;\n  \n  if (!changes || !changes.detected) {\n    return [{ json: { markdown: \"# Changelog\\n\\nNo changes detected.\" }}];\n  }\n  \n  // Start building the markdown\n  // Getting the filename from the input for the title\n  let fileNameWithoutExt = '';\n  try {\n    // Try to get the filename from the Loop Over Items node if available\n    fileNameWithoutExt = $('Loop over each comparison URL').first().json[\"\"][0];\n  } catch (e) {\n    // Fallback to a generic title if the loop node isn't available\n    fileNameWithoutExt = \"Website\";\n  }\n  \n  let markdown = `# ${fileNameWithoutExt} Changes\\n\\n`;\n  \n  // Process each section in the changes object\n  Object.values(changes.sections).forEach(section => {\n    markdown += `## ${section.name}\\n\\n`;\n    \n    // Process each change in this section\n    section.changes.forEach(change => {\n      switch (change.type) {\n        case 'changed':\n          markdown += `- **${change.displayPath}** changed from \\`${formatValue(change.old)}\\` to \\`${formatValue(change.new)}\\`\\n`;\n          break;\n          \n        case 'added':\n          markdown += `- **${change.displayPath}** was added with value \\`${formatValue(change.value)}\\`\\n`;\n          break;\n          \n        case 'removed':\n          markdown += `- **${change.displayPath}** was removed (previously \\`${formatValue(change.value)}\\`)\\n`;\n          break;\n          \n        case 'array_changed':\n          markdown += `- **${change.displayPath}** has changes:\\n`;\n          \n          // Handle additions\n          if (change.additions && change.additions.length > 0) {\n            markdown += `  - **Added**:\\n`;\n            change.additions.forEach(item => {\n              markdown += `    - \\`${formatValue(item)}\\`\\n`;\n            });\n          }\n          \n          // Handle deletions\n          if (change.deletions && change.deletions.length > 0) {\n            markdown += `  - **Removed**:\\n`;\n            change.deletions.forEach(item => {\n              markdown += `    - \\`${formatValue(item)}\\`\\n`;\n            });\n          }\n          break;\n      }\n    });\n    \n    markdown += '\\n';\n  });\n  \n  // Add summary section\n  markdown += `## Summary\\n\\n`;\n  markdown += `Total changes detected: **${changes.summary.totalChanges}**\\n\\n`;\n  markdown += `Generated on: **${new Date(changes.summary.timestamp).toLocaleDateString('en-US', {\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric'\n  })}**\\n`;\n  \n  // Return in the format expected by n8n\n  return [{ json: { markdown } }];\n}\n\n// Helper function to format values for markdown display\nfunction formatValue(value) {\n  if (value === null || value === undefined) {\n    return 'null';\n  } else if (typeof value === 'object') {\n    if (Array.isArray(value)) {\n      // For arrays, simplify to show length\n      if (value.length === 0) return '[]';\n      if (value.length > 3) {\n        return `[Array with ${value.length} items]`;\n      }\n      // For small arrays, show the items\n      return JSON.stringify(value).substring(0, 60) + (JSON.stringify(value).length > 60 ? '...' : '');\n    }\n    \n    // For objects with a name or key identifier, try to use that\n    if (value.name) return value.name;\n    if (value.title) return value.title;\n    if (value.id) return value.id;\n    if (value.planName) return value.planName;\n    if (value.question) return value.question;\n    \n    // For other objects, shorten to reasonable length\n    const objStr = JSON.stringify(value);\n    return objStr.substring(0, 60) + (objStr.length > 60 ? '...' : '');\n  } else if (typeof value === 'string') {\n    // For strings, add quoting\n    return value;\n  } else {\n    // For other primitives, convert to string\n    return String(value);\n  }\n}\n\n// Execute the function and return the markdown result\nreturn generateChangelogMarkdown();"
      },
      "typeVersion": 2
    },
    {
      "id": "16c9f196-6acf-4d3a-946b-727c121b503a",
      "name": "마크다운을 HTML로 변환",
      "type": "n8n-nodes-base.markdown",
      "position": [
        3480,
        -365
      ],
      "parameters": {
        "mode": "markdownToHtml",
        "options": {},
        "markdown": "={{ $json.markdown }}"
      },
      "typeVersion": 1
    },
    {
      "id": "3df4c31f-db47-40a5-9140-d2de7b1fbf2e",
      "name": "비교 문서 생성",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        3700,
        -365
      ],
      "parameters": {
        "title": "={{ $('Web scraping and data extraction agent').first().json.output.filename.replace(/\\.[^/.]+$/, '') + '-comparison.md' }}",
        "folderId": "default"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "id": "T3HEUOkeb37yLim7",
          "name": "Google Docs account"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "da24c1a3-fa3b-4b06-b5b9-78dd6d872756",
      "name": "결과를 비교 문서에 업데이트",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        3920,
        -365
      ],
      "parameters": {
        "actionsUi": {
          "actionFields": [
            {
              "text": "={{ $('Convert Markdown to HTML').item.json.data }}",
              "action": "insert"
            }
          ]
        },
        "operation": "update",
        "documentURL": "={{ $json.id }}"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "id": "T3HEUOkeb37yLim7",
          "name": "Google Docs account"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "b532d34b-0ac0-4a00-9949-a9a959e27b31",
      "name": "비교 파일로 비교 스프레드시트 업데이트",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4140,
        -365
      ],
      "parameters": {
        "columns": {
          "value": {
            "URL": "={{ $('Loop over each comparison URL').item.json.URL }}",
            "Comparison File": "=https://docs.google.com/document/d/{{ $json.documentId }}"
          },
          "schema": [
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Previous Week ID",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Previous Week ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Previous Week File Link",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Previous Week File Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Current Week File ID",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Current Week File ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Current Week File Link",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Current Week File Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Comparison File",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Comparison File",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "URL"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1e4oheZjmxb3P7OXGY0uLWZKz2ENcp7XlEpIloOtRHEk/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1e4oheZjmxb3P7OXGY0uLWZKz2ENcp7XlEpIloOtRHEk",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1e4oheZjmxb3P7OXGY0uLWZKz2ENcp7XlEpIloOtRHEk/edit?usp=drivesdk",
          "cachedResultName": "BrightData Scraping Comparison"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "vnXMSwscCP06bp9u",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "7ef3ba20-c79e-4d49-8a68-c11d20c77def",
      "name": "비교 결과 이메일 전송",
      "type": "n8n-nodes-base.gmail",
      "position": [
        4340,
        -260
      ],
      "webhookId": "8d51cb0f-f585-4222-93dd-2fffcead588e",
      "parameters": {
        "sendTo": "dave@emberautomation.com",
        "message": "={{ $('Convert Markdown to HTML').item.json.data }}",
        "options": {},
        "subject": "={{ $now.format('yyyy-MM-dd') }}: {{ $('Loop over each comparison URL').item.json.URL }} weekly comparison"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "nkZOm8cNEGHWhTE4",
          "name": "Gmail account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a0926fe8-80c2-456b-b9c2-4dc1675c408c",
      "name": "스티키 노트",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -540,
        -1340
      ],
      "parameters": {
        "width": 760,
        "height": 1060,
        "content": "# BrightData Weekly Comparison\n## Overview\nThis workflow tracks changes on web pages, compares data, generates change reports, saves to Drive, and sends email notifications. **The workflow runs automatically on a weekly basis.**\n\n## Prerequisites\n- **Bright Data MCP Server**: Set up a Bright Data MCP server for web scraping\n- **n8n MCP Client Node**: Install the community node from `n8n-nodes-mcp` (https://www.npmjs.com/package/n8n-nodes-mcp)\n\n## Setup Steps\n1. **Duplicate Spreadsheet**\n   - Make a copy of the comparison spreadsheet: [Sheet to Copy](https://docs.google.com/spreadsheets/d/1oPyAaTS8GMqlaBcyCO7G7MRtzMUUaOnA45JfWCzcCa8/edit?usp=sharing)\n   - Update the URLs of web pages to track\n\n2. **Configure Variables**\n   - Open the \"Set workflow variables\" node\n   - Update these values:\n     - `DriveFolderID`: Your Google Drive folder ID\n     - `ComparisonSpreadsheetFileID`: `1e4oheZjmxb3P7OXGY0uLWZKz2ENcp7XlEpIloOtRHEk` (or your copied spreadsheet ID)\n     - `ComparisonSpreadsheetSheetName`: Sheet name (usually \"Sheet1\")\n     - `Email`: Where to send reports\n     - `IsTest`: Set to `true` only for testing (set to `false` for regular operation)\n\n3. **Configure Bright Data MCP**\n   - Set up your Bright Data MCP credentials in the MCP client node\n   - Configure the MCP server using the documentation: https://github.com/luminati-io/brightdata-mcp\n\n4. **Set Up Credentials**\n   - Configure credentials for:\n     - Google Sheets\n     - Google Drive\n     - Google Docs\n     - Gmail\n     - OpenAI (or alternative AI provider)\n     - Bright Data MCP\n\n5. **Run Workflow**\n   - Execute the workflow manually to test\n   - Check your Drive folder and email for results\n   - **Once setup is complete, the workflow will run automatically every week**"
      },
      "typeVersion": 1
    },
    {
      "id": "33c8b369-b6f7-4bb9-87e2-d202d998255d",
      "name": "GPT-4.1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        620,
        -145
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1",
          "cachedResultName": "gpt-4.1"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "NuECwZyKpEfWhSN1",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "700e8bb2-607d-4889-b248-88bf6464c587",
      "name": "스케줄 트리거",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -480,
        -120
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                3
              ],
              "triggerAtHour": 12
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c2919b53-c13f-4033-86f2-3b4e2e28dfa8",
      "name": "마크다운으로 스크래핑",
      "type": "n8n-nodes-mcp.mcpClientTool",
      "position": [
        740,
        -145
      ],
      "parameters": {
        "toolName": "scrape_as_markdown",
        "operation": "executeTool",
        "toolParameters": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Tool_Parameters', ``, 'json') }}"
      },
      "credentials": {
        "mcpClientApi": {
          "id": "mO1My0js13704jqM",
          "name": "MCP Client (STDIO) account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cbbfbf09-9d2b-4c3b-bcbc-fc43f198f0c0",
      "name": "자동 수정 출력 파서",
      "type": "@n8n/n8n-nodes-langchain.outputParserAutofixing",
      "position": [
        640,
        20
      ],
      "parameters": {
        "options": {
          "prompt": "Instructions:\n--------------\n{instructions}\n--------------\nCompletion:\n--------------\n{completion}\n--------------\n\nAbove, the Completion did not satisfy the constraints given in the Instructions.\nError:\n--------------\n{error}\n--------------\n\nPlease try again. Please only respond with an answer that satisfies the constraints laid out in the Instructions:"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f3766efe-53a7-4311-9b53-af9f8d11b292",
      "name": "스티키 노트1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -540,
        -260
      ],
      "parameters": {
        "color": 2,
        "width": 220,
        "height": 340,
        "content": "## Scheduled Weekly"
      },
      "typeVersion": 1
    },
    {
      "id": "93f1107c-8e81-439b-a912-5900e36afd8b",
      "name": "스티키 노트2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -280,
        -260
      ],
      "parameters": {
        "color": 3,
        "width": 620,
        "height": 340,
        "content": "## Initialization\nInitializes the workflow variables, reads the main spreadsheet, then merges the spreadsheet results with the main workflow variables. "
      },
      "typeVersion": 1
    },
    {
      "id": "f4882880-6ee4-4a44-9967-1be01de7151c",
      "name": "스티키 노트3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -520
      ],
      "parameters": {
        "color": 4,
        "width": 400,
        "height": 780,
        "content": "## AI Scraping\nFor the given URL, the agent will use the Scrape as Markdown tool to scrape the page getting the content as Markdown. It will then generate a JSON structure, extracting out relevant information from the page. "
      },
      "typeVersion": 1
    },
    {
      "id": "8f6da1fd-c91a-4c99-94f8-b2464a0786be",
      "name": "스티키 노트4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1020,
        -520
      ],
      "parameters": {
        "color": 5,
        "width": 860,
        "height": 400,
        "content": "## Process current week results\nThe agent's response is turned into a binary file and then saved in Google Drive for the next week. Then the main spreadsheet is updated with that file. Finally checking if we have a previous week to compare this week to. If not, we finish and move on to the next item. If we do, then we move on and process the previous week's results vs the current week. "
      },
      "typeVersion": 1
    },
    {
      "id": "25f758b4-2e11-4cde-bcc3-1a8e53106d29",
      "name": "스티키 노트5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1900,
        -520
      ],
      "parameters": {
        "color": 6,
        "width": 640,
        "height": 400,
        "content": "## Process previous week results\nRead the previous week's ID and download the file from Google Drive. Then, set variables ready for processing. "
      },
      "typeVersion": 1
    },
    {
      "id": "f8d7c276-9540-431d-860d-10e15b769fe4",
      "name": "스티키 노트6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2560,
        -520
      ],
      "parameters": {
        "color": 7,
        "width": 440,
        "height": 400,
        "content": "## Mocking\nIf we are in test mode, then this will mock example changes. Otherwise, it will carry on as normal. "
      },
      "typeVersion": 1
    },
    {
      "id": "c2dfbe5e-e79e-4cc8-91f2-a61bfef2721e",
      "name": "스티키 노트7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3020,
        -520
      ],
      "parameters": {
        "color": 2,
        "width": 1260,
        "height": 400,
        "content": "## Current week vs previous week comparison\nUsing code notes, we detect the changes from the previous week vs the current week and then convert that to a Markdown document and then use the Markdown to HTML node.  Finally, creating a document in Google Docs, and then updating the main spreadsheet with that comparison document. "
      },
      "typeVersion": 1
    },
    {
      "id": "a261bcd8-91a1-40f4-928f-19013b68b998",
      "name": "금주 JSON 응답을 파일로 변환",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        1060,
        -365
      ],
      "parameters": {
        "options": {},
        "operation": "toJson"
      },
      "typeVersion": 1.1
    },
    {
      "id": "dc49334a-6d00-4476-b84c-7bddfa3c0911",
      "name": "스티키 노트8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4300,
        -520
      ],
      "parameters": {
        "width": 380,
        "height": 400,
        "content": "## Send the comparison email"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "3556e422-eddc-40df-8f4f-860d621258d4",
  "connections": {
    "33c8b369-b6f7-4bb9-87e2-d202d998255d": {
      "ai_languageModel": [
        [
          {
            "node": "c50e3ec4-c3bf-4417-94ad-5b57ad6424da",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "cbbfbf09-9d2b-4c3b-bcbc-fc43f198f0c0",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "700e8bb2-607d-4889-b248-88bf6464c587": {
      "main": [
        [
          {
            "node": "6d4b38bd-fb58-4675-9b83-ade043914d65",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "40b828f7-08f2-41ea-a6f7-595c5e4ae3e0": {
      "main": [
        [
          {
            "node": "af562b9f-3cfc-4715-ae47-779a0554e7d2",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "dd764b6d-d412-44e6-8816-e7b66bbb44c6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c2919b53-c13f-4033-86f2-3b4e2e28dfa8": {
      "ai_tool": [
        [
          {
            "node": "c50e3ec4-c3bf-4417-94ad-5b57ad6424da",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "6d4b38bd-fb58-4675-9b83-ade043914d65": {
      "main": [
        [
          {
            "node": "45eefb28-dce0-4fc3-81a1-865762c73226",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "16c9f196-6acf-4d3a-946b-727c121b503a": {
      "main": [
        [
          {
            "node": "3df4c31f-db47-40a5-9140-d2de7b1fbf2e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a2966ed3-e998-47ca-83b3-b7dc4832bc8f": {
      "ai_outputParser": [
        [
          {
            "node": "cbbfbf09-9d2b-4c3b-bcbc-fc43f198f0c0",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "cbbfbf09-9d2b-4c3b-bcbc-fc43f198f0c0": {
      "ai_outputParser": [
        [
          {
            "node": "c50e3ec4-c3bf-4417-94ad-5b57ad6424da",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "3df4c31f-db47-40a5-9140-d2de7b1fbf2e": {
      "main": [
        [
          {
            "node": "da24c1a3-fa3b-4b06-b5b9-78dd6d872756",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "af562b9f-3cfc-4715-ae47-779a0554e7d2": {
      "main": [
        [
          {
            "node": "dd764b6d-d412-44e6-8816-e7b66bbb44c6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "dd764b6d-d412-44e6-8816-e7b66bbb44c6": {
      "main": [
        [
          {
            "node": "e5a8b7c1-53ec-4a26-8791-30db494cde92",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "301dfc46-f1d4-4b1a-892b-25ecb4495b77": {
      "main": [
        [
          {
            "node": "036d00c9-7414-4883-ac56-ef9368195b85",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c04cec36-1664-48d7-a9ae-a5665bc2c188": {
      "main": [
        [],
        [
          {
            "node": "c50e3ec4-c3bf-4417-94ad-5b57ad6424da",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c1f69dc5-6612-4575-aaf4-1d6a7a70c423": {
      "main": [
        [
          {
            "node": "e4a1fd2c-e1a5-4065-a9c8-76d1c854af95",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7ef3ba20-c79e-4d49-8a68-c11d20c77def": {
      "main": [
        [
          {
            "node": "c04cec36-1664-48d7-a9ae-a5665bc2c188",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "45eefb28-dce0-4fc3-81a1-865762c73226": {
      "main": [
        [
          {
            "node": "6ddda34f-556e-49a5-a103-7641a3f0598d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "67b8ee0a-2ab0-43cd-b24f-0c8ba6b04cd1": {
      "main": [
        [
          {
            "node": "40b828f7-08f2-41ea-a6f7-595c5e4ae3e0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "036d00c9-7414-4883-ac56-ef9368195b85": {
      "main": [
        [
          {
            "node": "67b8ee0a-2ab0-43cd-b24f-0c8ba6b04cd1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "32934604-9e72-4f6a-aa55-fc0abff1d85c": {
      "main": [
        [
          {
            "node": "301dfc46-f1d4-4b1a-892b-25ecb4495b77",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "c04cec36-1664-48d7-a9ae-a5665bc2c188",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c50e3ec4-c3bf-4417-94ad-5b57ad6424da": {
      "main": [
        [
          {
            "node": "a261bcd8-91a1-40f4-928f-19013b68b998",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e5a8b7c1-53ec-4a26-8791-30db494cde92": {
      "main": [
        [
          {
            "node": "16c9f196-6acf-4d3a-946b-727c121b503a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "da24c1a3-fa3b-4b06-b5b9-78dd6d872756": {
      "main": [
        [
          {
            "node": "b532d34b-0ac0-4a00-9949-a9a959e27b31",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a261bcd8-91a1-40f4-928f-19013b68b998": {
      "main": [
        [
          {
            "node": "c1f69dc5-6612-4575-aaf4-1d6a7a70c423",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6ddda34f-556e-49a5-a103-7641a3f0598d": {
      "main": [
        [
          {
            "node": "c04cec36-1664-48d7-a9ae-a5665bc2c188",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b532d34b-0ac0-4a00-9949-a9a959e27b31": {
      "main": [
        [
          {
            "node": "7ef3ba20-c79e-4d49-8a68-c11d20c77def",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e4a1fd2c-e1a5-4065-a9c8-76d1c854af95": {
      "main": [
        [
          {
            "node": "32934604-9e72-4f6a-aa55-fc0abff1d85c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급 - 인공지능, 마케팅

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수35
카테고리2
노드 유형18
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

저자
Daniel Shashko

Daniel Shashko

@tomax

AI automation specialist and a marketing enthusiast. More than 6 years of experience in SEO/GEO. Senior SEO at Bright Data.

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34