AutomationFlowsAI & RAG › Generate Reddit Customer Leads From a Product URL with Openai and Firecrawl

Generate Reddit Customer Leads From a Product URL with Openai and Firecrawl

ByJoseph @mjomba on n8n.io

Production-ready Reddit lead generation system with progressive data loading for optimal UX. This workflow integrates with a web frontend, sending results in real-time as they're processed instead of waiting for everything to complete.

Webhook trigger★★★★★ complexityAI-powered56 nodesOutput Parser StructuredAgentRedditOpenAI ChatHTTP Request@Mendable/N8N Nodes Firecrawl
AI & RAG Trigger: Webhook Nodes: 56 Complexity: ★★★★★ AI nodes: yes Added:

This workflow corresponds to n8n.io template #12884 — we link there as the canonical source.

This workflow follows the Agent → 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 →

Download .json
{
  "nodes": [
    {
      "id": "0c5652da-95ff-4c9e-be66-0ae21e591de7",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1888,
        208
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"keyword1\": \"keyword or phrase 1\",\n  \"keyword2\": \"keyword or phrase 2\",\n  \"keyword3\": \"keyword or phrase 3\",\n  \"keyword4\": \"keyword or phrase 4\",\n  \"keyword5\": \"keyword or phrase 5\",\n  \"keyword6\": \"keyword or phrase 6\",\n  \"keyword7\": \"keyword or phrase 7\",\n  \"keyword8\": \"keyword or phrase 8\",\n  \"keyword9\": \"keyword or phrase 9\",\n  \"keyword10\": \"keyword or phrase 10\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "7f67cc7d-1ce8-4115-9758-437cf05c58a9",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1200,
        752
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "subreddit"
            },
            {
              "fieldToAggregate": "title"
            },
            {
              "fieldToAggregate": "body"
            },
            {
              "fieldToAggregate": "postUrl"
            },
            {
              "fieldToAggregate": "createdAt"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1ee80d75-bad0-41b7-aa82-3584679a0881",
      "name": "Structured Output Parser1",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        976,
        720
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\"assessment\": \"relevant/irrelevant\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "21fe7ff8-73ef-45fc-86e1-b961f646246c",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1632,
        624
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "9f3e36f3-5913-406e-b65d-3b728d070fb1",
      "name": "Aggregate3",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1200,
        496
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "output.assessment"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3baea4b6-10f1-4bb9-b905-7f5113187272",
      "name": "Reddit Posts Keywords Generator",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1744,
        -16
      ],
      "parameters": {
        "text": "=Product landing Page Description:  {{ $('Scrape Product URL and get its content').item.json.data.markdown }}",
        "options": {
          "systemMessage": "=# Reddit Keyword Extraction Agent\n\nYou are a specialized AI agent designed to analyze product landing pages and extract optimal keywords for Reddit lead generation.\n\n## Your Task\nAnalyze the provided markdown content from a landing page scrape and generate 10 highly targeted keywords that will help identify relevant Reddit threads where potential customers are discussing problems, needs, or topics related to this product.\n\n## Analysis Process\n\n1. **Identify the Core Product/Service**: Understand what the product does, who it's for, and what problems it solves.\n\n2. **Extract Key Elements**:\n   - Primary pain points the product addresses\n   - Target audience characteristics and personas\n   - Industry or niche terminology\n   - Use cases and applications\n   - Competitor or alternative solution names\n   - Problem statements customers express\n   - Feature categories that indicate need\n\n3. **Consider Reddit Search Behavior**: Think about how real people describe their problems on Reddit before they know solutions exist.\n\n## Keyword Selection Criteria\n\n- **Problem-focused**: Keywords should reflect issues people actively discuss (e.g., \"struggling with project management\" rather than just \"project management software\")\n- **Natural language**: Use phrases people actually type in Reddit searches\n- **Varied specificity**: Mix broad industry terms with specific pain points\n- **Context-aware**: Include both technical and casual language variations\n- **Subreddit-friendly**: Keywords should match topics discussed in relevant subreddits\n\n## Output Format\n\nProvide ONLY a JSON object with 10 separate keyword fields. NO additional text, explanation, or markdown formatting.\n\n**Structure:**\n```json\n{\n  \"keyword1\": \"keyword or phrase 1\",\n  \"keyword2\": \"keyword or phrase 2\",\n  \"keyword3\": \"keyword or phrase 3\",\n  \"keyword4\": \"keyword or phrase 4\",\n  \"keyword5\": \"keyword or phrase 5\",\n  \"keyword6\": \"keyword or phrase 6\",\n  \"keyword7\": \"keyword or phrase 7\",\n  \"keyword8\": \"keyword or phrase 8\",\n  \"keyword9\": \"keyword or phrase 9\",\n  \"keyword10\": \"keyword or phrase 10\"\n}\n```\n\n**Example Output** (for a freelance time-tracking tool):\n```json\n{\n  \"keyword1\": \"tracking billable hours freelance\",\n  \"keyword2\": \"how to invoice clients accurately\",\n  \"keyword3\": \"time management for consultants\",\n  \"keyword4\": \"freelancer productivity tips\",\n  \"keyword5\": \"tracking multiple client projects\",\n  \"keyword6\": \"automated time tracking tools\",\n  \"keyword7\": \"best way to log work hours\",\n  \"keyword8\": \"freelance accounting software recommendations\",\n  \"keyword9\": \"struggling with time estimates\",\n  \"keyword10\": \"client billing disputes hours\"\n}\n```\n\n## Important Guidelines\n\n- Keep each keyword/phrase between 2-6 words for optimal Reddit search results\n- Avoid generic terms that would return too many irrelevant results\n- Include a mix of: problem statements, use cases, target roles/personas, and industry terms\n- Do NOT include the product name itself\n- Focus on discoverability: what would someone search before finding this solution?\n- Prioritize keywords that indicate buying intent or active problem-solving\n- Output MUST be valid JSON only - no markdown code blocks, no explanatory text\n\n## Example Comparison\n\nIf analyzing a landing page for a time-tracking tool for freelancers:\n- \u2705 GOOD: \"tracking billable hours\", \"freelance time management\", \"client invoicing struggles\"\n- \u274c BAD: \"productivity\", \"software\", \"business tools\"\n\nNow analyze the provided markdown content and generate the 10 optimal Reddit search keywords in the exact JSON format specified above."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "83188d1b-1e0b-4678-b5f4-1dcba012d3eb",
      "name": "Posts Relevance AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        848,
        496
      ],
      "parameters": {
        "text": "=title: {{ $('Clean results').item.json.title }}\nBody: {{ $('Clean results').item.json.body }}",
        "options": {
          "systemMessage": "=The following is a post search result from reddit in previous n8n nodes for the keyword  {{ $('Reddit Posts Keywords Generator').item.json.output.keyword1 }}\n\nThe posts should be of themes related to the keyword so that I can engage in comments to promote my product \"{{ $('Scrape Product URL and get its content').item.json.data.metadata.ogTitle }}\", desccription \"{{ $('Scrape Product URL and get its content').item.json.data.metadata['og:description'][0] }}\"\n\nPlease Check if the post is relevant, if it is please add assement: relevant or irrelevant\n\n{\n\"assessment\": \"relevant/irrelevant\"\n}"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "b840db51-a24e-4d46-8ada-3361dc560e22",
      "name": "Clean results",
      "type": "n8n-nodes-base.code",
      "position": [
        624,
        624
      ],
      "parameters": {
        "jsCode": "// Loop through all incoming items and extract the required fields\nreturn $input.all().map(item => {\n  return {\n    json: {\n      subreddit: item.json.subreddit ?? 'not_applicable',\n      title: item.json.title ?? 'not_applicable',\n      body: item.json.selftext ?? 'not_applicable',\n      postUrl: item.json.url ?? 'not_applicable',\n      createdAt: item.json.created_utc \n        ? new Date(item.json.created_utc * 1000).toISOString() // converts UTC seconds to ISO datetime\n        : 'not_applicable'\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "de3c10e5-be6a-46d6-8d26-a2b9eec9ee1d",
      "name": "Search for Posts (Keyword/Phrase)",
      "type": "n8n-nodes-base.reddit",
      "position": [
        400,
        624
      ],
      "parameters": {
        "limit": 10,
        "keyword": "={{ $('Reddit Posts Keywords Generator').item.json.output.keyword1 }}",
        "location": "allReddit",
        "operation": "search",
        "additionalFields": {
          "sort": "hot"
        }
      },
      "credentials": {
        "redditOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3d129cb6-b34b-4710-800e-133e39a77f47",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        -80
      ],
      "parameters": {
        "width": 2464,
        "height": 464,
        "content": "## Process Product URL, Send Website Analysis and Keywords to Server/Frontend"
      },
      "typeVersion": 1
    },
    {
      "id": "74f112b9-2820-4742-be7f-a316ec3b188f",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -176,
        -16
      ],
      "parameters": {
        "path": "b2d7fb9a-f92c-4174-998e-58e902d0ce81",
        "options": {},
        "httpMethod": "POST",
        "authentication": "headerAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "38e67c19-4c0d-46da-9cb4-881e07a57931",
      "name": "OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        752,
        208
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "60f7e528-0bfd-437e-bfd0-f04f7f6e26bc",
      "name": "Structured Output Parser4",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        880,
        208
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"website_summary\": \"Two sentence summary of what the website/product is and its core value proposition. Keep it clear and concise.\",\n  \"target_market\": \"A single paragraph describing the intended audience, their pain points, and why this product/service appeals to them. Include specific characteristics or demographics if evident from the content.\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "12b084df-808c-44da-9061-21900fc28b33",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        1088,
        -16
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "f13da266-d978-4023-9323-a8169743a847",
              "name": "title",
              "type": "string",
              "value": "={{ $('Sanitize Results').item.json.title }}"
            },
            {
              "id": "e97e0e63-136c-4f2c-8c98-a59e4eb49f94",
              "name": "cta",
              "type": "string",
              "value": "={{ $('Sanitize Results').item.json.description }}"
            },
            {
              "id": "b2ec2274-5ef9-4ffb-81ab-8ad1e394a960",
              "name": "website_summary",
              "type": "string",
              "value": "={{ $json.output.website_summary }}"
            },
            {
              "id": "8e82bf38-6b39-4a14-aa76-990b403e4946",
              "name": "target_market_analysis",
              "type": "string",
              "value": "={{ $json.output.target_market }}"
            },
            {
              "id": "38482346-14e7-4876-9a8d-95430a9c99a1",
              "name": "preview_image",
              "type": "string",
              "value": "={{ $('Sanitize Results').item.json.image }}"
            },
            {
              "id": "8235ce16-0489-442a-9fb4-36efec7719b7",
              "name": "favicon",
              "type": "string",
              "value": "={{ $('Sanitize Results').item.json.favicon }}"
            },
            {
              "id": "ca87e1a2-0c39-49f2-aa1c-94f25065695a",
              "name": "searchId",
              "type": "string",
              "value": "={{ $('Webhook').item.json.body.searchId }}"
            },
            {
              "id": "fe394353-cc53-4d61-8dbf-301148b9cc11",
              "name": "stage",
              "type": "string",
              "value": "website_analysis"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "870b8682-833f-4c15-b9bb-ee6cf0563417",
      "name": "OpenAI Chat Model2",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        848,
        720
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6d847db9-9f96-406c-a416-99af6e9674d6",
      "name": "Aggregate5",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        3344,
        208
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "subreddit"
            },
            {
              "fieldToAggregate": "title"
            },
            {
              "fieldToAggregate": "body"
            },
            {
              "fieldToAggregate": "postUrl"
            },
            {
              "fieldToAggregate": "createdAt"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8a5b72e6-9b60-4be1-a206-51f83deceb90",
      "name": "Structured Output Parser5",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        3120,
        192
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\"assessment\": \"relevant/irrelevant\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "630c4fbf-dfe4-48d7-b608-61434e77d97a",
      "name": "Merge3",
      "type": "n8n-nodes-base.merge",
      "position": [
        3568,
        96
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "8c46816e-bbe6-4350-835e-912765cf4d14",
      "name": "Aggregate6",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        3344,
        -32
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "output.assessment"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3bf798ad-3f52-4231-b4d0-83dbce730428",
      "name": "Posts Relevance AI Agent2",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2992,
        -32
      ],
      "parameters": {
        "text": "=title: {{ $('Clean results2').item.json.title }}\nBody: {{ $('Clean results2').item.json.body }}",
        "options": {
          "systemMessage": "=The following is a post search result from reddit in previous n8n nodes for the keyword  {{ $('Reddit Posts Keywords Generator').item.json.output.keyword1 }}\n\nThe posts should be of themes related to the keyword so that I can engage in comments to promote my product \"{{ $('Scrape Product URL and get its content').item.json.data.metadata.ogTitle }}\", desccription \"{{ $('Scrape Product URL and get its content').item.json.data.metadata['og:description'][0] }}\"\n\nPlease Check if the post is relevant, if it is please add assement: relevant or irrelevant\n\n{\n\"assessment\": \"relevant/irrelevant\"\n}"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "87e4aa6e-6ebb-469a-af38-14c15e4448a5",
      "name": "Clean results2",
      "type": "n8n-nodes-base.code",
      "position": [
        2768,
        96
      ],
      "parameters": {
        "jsCode": "// Loop through all incoming items and extract the required fields\nreturn $input.all().map(item => {\n  return {\n    json: {\n      subreddit: item.json.subreddit ?? 'not_applicable',\n      title: item.json.title ?? 'not_applicable',\n      body: item.json.selftext ?? 'not_applicable',\n      postUrl: item.json.url ?? 'not_applicable',\n      createdAt: item.json.created_utc \n        ? new Date(item.json.created_utc * 1000).toISOString() // converts UTC seconds to ISO datetime\n        : 'not_applicable'\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "63915944-b1b3-4069-a358-88fa03aa4159",
      "name": "Search for Posts (Keyword/Phrase)2",
      "type": "n8n-nodes-base.reddit",
      "position": [
        2544,
        96
      ],
      "parameters": {
        "limit": 10,
        "keyword": "={{ $('Reddit Posts Keywords Generator').item.json.output.keyword2 }}",
        "location": "allReddit",
        "operation": "search",
        "additionalFields": {
          "sort": "hot"
        }
      },
      "credentials": {
        "redditOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "67b9c808-fadc-49ea-ae23-d044d7dd2972",
      "name": "OpenAI Chat Model3",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2992,
        192
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ca78c115-c11e-4340-b2e2-73db050f6087",
      "name": "Aggregate9",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        4032,
        768
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "subreddit"
            },
            {
              "fieldToAggregate": "title"
            },
            {
              "fieldToAggregate": "body"
            },
            {
              "fieldToAggregate": "postUrl"
            },
            {
              "fieldToAggregate": "createdAt"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "14c5fa1b-4f89-45a1-ac08-251ef8609574",
      "name": "Structured Output Parser7",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        3824,
        768
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\"assessment\": \"relevant/irrelevant\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "efbed6ed-334f-4e35-9ca4-5def64c01236",
      "name": "Merge5",
      "type": "n8n-nodes-base.merge",
      "position": [
        4256,
        672
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "b845e2bd-0353-4c9e-9ac7-977068965443",
      "name": "Aggregate10",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        4032,
        624
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "output.assessment"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3abacb05-9436-41fb-9122-53b6698a34e9",
      "name": "Posts Relevance AI Agent4",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        3696,
        624
      ],
      "parameters": {
        "text": "=title: {{ $('Clean results4').item.json.title }}\nBody: {{ $('Clean results4').item.json.body }}",
        "options": {
          "systemMessage": "=The following is a post search result from reddit in previous n8n nodes for the keyword  {{ $('Split Out1').item.json.keywords }}\n\nThe posts should be of themes related to the keyword so that I can engage in comments to promote my product \"{{ $('Scrape Product URL and get its content').item.json.data.metadata.ogTitle }}\", desccription \"{{ $('Scrape Product URL and get its content').item.json.data.metadata['og:description'][0] }}\"\n\nPlease Check if the post is relevant, if it is please add assement: relevant or irrelevant\n\n{\n\"assessment\": \"relevant/irrelevant\"\n}"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "619719b7-a33a-4dea-8132-f90977084fc8",
      "name": "Clean results4",
      "type": "n8n-nodes-base.code",
      "position": [
        3456,
        672
      ],
      "parameters": {
        "jsCode": "// Loop through all incoming items and extract the required fields\nreturn $input.all().map(item => {\n  return {\n    json: {\n      subreddit: item.json.subreddit ?? 'not_applicable',\n      title: item.json.title ?? 'not_applicable',\n      body: item.json.selftext ?? 'not_applicable',\n      postUrl: item.json.url ?? 'not_applicable',\n      createdAt: item.json.created_utc \n        ? new Date(item.json.created_utc * 1000).toISOString() // converts UTC seconds to ISO datetime\n        : 'not_applicable'\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "8cac8a56-8a75-4550-b1f2-f9784c55bb27",
      "name": "Search for Posts (Keyword/Phrase)4",
      "type": "n8n-nodes-base.reddit",
      "position": [
        3232,
        672
      ],
      "parameters": {
        "limit": 10,
        "keyword": "={{ $json.keywords }}",
        "location": "allReddit",
        "operation": "search",
        "additionalFields": {
          "sort": "hot"
        }
      },
      "credentials": {
        "redditOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cb4cd520-d269-4526-afa4-5be42cbd0f73",
      "name": "Split Out1",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        2784,
        672
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "keywords"
      },
      "typeVersion": 1
    },
    {
      "id": "ad9486e0-ff14-4b60-bc19-74e598e03519",
      "name": "Loop Over Items1",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        3008,
        672
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "dbc94d02-7c7c-40d1-a483-e239df618c0c",
      "name": "Aggregate11",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        3456,
        464
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "passed_post"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5ff4dfff-1330-49d4-90a9-5f9fe523826c",
      "name": "OpenAI Chat Model5",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        3696,
        768
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e0fa1c22-c012-4769-8ef8-f0deaa7f4e31",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2288,
        -80
      ],
      "parameters": {
        "width": 1936,
        "height": 464,
        "content": "## Process and send conversations for Keyword #2"
      },
      "typeVersion": 1
    },
    {
      "id": "ec54a767-e0be-4084-9e5f-dbe06b1df078",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        432
      ],
      "parameters": {
        "width": 2016,
        "height": 496,
        "content": "## Process and send conversations for Keyword #1"
      },
      "typeVersion": 1
    },
    {
      "id": "492af242-f6c3-4177-a3be-e2508daec61a",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2288,
        432
      ],
      "parameters": {
        "width": 2336,
        "height": 496,
        "content": "## Process and send conversations for Keyword #3 - #10"
      },
      "typeVersion": 1
    },
    {
      "id": "4d0a5307-6fd7-481b-a3de-b9fbc84bfee1",
      "name": "Set Environment Variables",
      "type": "n8n-nodes-base.set",
      "position": [
        32,
        -16
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e0558f12-c17a-4bad-b482-438ff599f71a",
              "name": "N8N_WEBHOOK_API_KEY",
              "type": "string",
              "value": "your-secret-key/api-key"
            },
            {
              "id": "a48acfbb-0216-4bf9-9295-ffc18aba750e",
              "name": "BACKEND_API_URL",
              "type": "string",
              "value": "your-ngrok-url/railway-server-base-url"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "23f69bb7-4150-4c19-837b-3c7c5e972bff",
      "name": "Sanitize Results",
      "type": "n8n-nodes-base.code",
      "position": [
        512,
        -16
      ],
      "parameters": {
        "jsCode": "return [\n  {\n    json: {\n      markdown: $input.first()?.json?.data?.markdown ?? 'not_applicable',\n      title: $input.first()?.json?.data?.metadata?.['og:title']?.[0] ?? 'not_applicable',\n      image: $input.first()?.json?.data?.metadata?.['og:image']?.[0] ?? 'not_applicable',\n      description: $input.first()?.json?.data?.metadata?.['og:description'] ?? 'not_applicable',\n      favicon: $input.first()?.json?.data?.metadata?.favicon ?? 'not_applicable'\n    }\n  }\n]\n"
      },
      "typeVersion": 2
    },
    {
      "id": "9d52e481-9595-42ad-b791-dd539d3ae888",
      "name": "Analyze Product URL Scrape",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        736,
        -16
      ],
      "parameters": {
        "text": "=site title: {{ $json.title }}\nmarkdown content: {{ $json.markdown }}\ncta: {{ $json.description }}",
        "options": {
          "systemMessage": "=You are an expert landing page analyzer specializing in extracting key business insights from website content. Your task is to analyze scraped landing page data and provide concise, actionable summaries.\n\n## Input Data\nYou will receive the following data from the scraping node:\n- **markdown_content**: The full markdown-formatted content of the landing page (always present)\n- **cta**: The primary call-to-action text from the page (may be marked as \"not_available\")\n\n## Instructions\n1. Only use data that is present. If any input shows \"not_available\", disregard it entirely.\n2. Focus your analysis on the markdown content as the primary source of truth.\n3. Analyze the landing page holistically to identify the product/service, its value proposition, and intended audience.\n4. Provide insights that would be useful for marketing, sales, or product teams.\n\n## Output Format\nReturn a valid JSON object with exactly this structure:\n\n```json\n{\n  \"website_summary\": \"Two sentence summary of what the website/product is and its core value proposition. Keep it clear and concise.\",\n  \"target_market\": \"A single paragraph describing the intended audience, their pain points, and why this product/service appeals to them. Include specific characteristics or demographics if evident from the content.\"\n}\n```\n\n## Output Requirements\n- **website_summary**: Exactly 2 sentences. First sentence should describe what the product is, second should describe its main benefit or value proposition.\n- **target_market**: One paragraph (3-5 sentences). Should identify who would benefit most, what problems it solves for them, and any implicit audience signals from the landing page.\n- Return only valid JSON with no additional text, markdown formatting, or explanations.\n- Use clear, professional language appropriate for business stakeholders."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "92974151-960e-40b4-a263-bbc10247d947",
      "name": "Sanitize JSON Values",
      "type": "n8n-nodes-base.code",
      "position": [
        1296,
        -16
      ],
      "parameters": {
        "jsCode": "/**\n * Ultra-safe sanitizer for AI / JSON payloads in n8n\n * Also removes wrapping square brackets: [ ... ]\n */\n\nfunction sanitizeForAI(value) {\n  if (value === null || value === undefined) {\n    return '';\n  }\n\n  // If array or object, stringify safely first\n  if (typeof value === 'object') {\n    try {\n      value = JSON.stringify(value);\n    } catch (e) {\n      value = String(value);\n    }\n  }\n\n  if (typeof value !== 'string') {\n    value = String(value);\n  }\n\n  value = value\n    // Trim early to detect wrapping brackets\n    .trim()\n\n    // Remove wrapping square brackets ONLY if they enclose entire string\n    .replace(/^\\[\\s*(.*?)\\s*\\]$/, '$1')\n\n    // Normalize unicode (smart quotes, odd chars)\n    .normalize('NFKC')\n\n    // Normalize newlines\n    .replace(/\\r\\n/g, '\\n')\n    .replace(/\\r/g, '\\n')\n\n    // Remove control characters except newline & tab\n    .replace(/[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F]/g, '')\n\n    // Escape backslashes\n    .replace(/\\\\/g, '\\\\\\\\')\n\n    // Escape double quotes\n    .replace(/\"/g, '\\\\\"')\n\n    // Replace non-breaking spaces\n    .replace(/\\u00A0/g, ' ')\n\n    // Collapse excessive spaces (preserve newlines)\n    .replace(/[ \\t]{2,}/g, ' ')\n\n    // Final trim\n    .trim();\n\n  return value;\n}\n\nconst input = $input.first().json;\n\nreturn [\n  {\n    json: {\n      title: sanitizeForAI(input.title),\n      cta: sanitizeForAI(input.cta),\n      website_summary: sanitizeForAI(input.website_summary),\n      target_market_analysis: sanitizeForAI(input.target_market_analysis),\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "b7cad7e8-3579-443d-b06e-de68b5660155",
      "name": "Send keywords to Server",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2096,
        -16
      ],
      "parameters": {
        "url": "={{ $('Set Environment Variables').item.json.BACKEND_API_URL }}api/webhook/n8n ",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"searchId\": \"{{ $('Edit Fields').item.json.searchId }}\",\n  \"stage\": \"keywords_generated\",\n  \"keywords\": {\n    \"keyword1\": \"{{ $json.output.keyword1 }}\",\n    \"keyword2\": \"{{ $json.output.keyword2 }}\",\n    \"keyword3\": \"{{ $json.output.keyword3 }}\",\n    \"keyword4\": \"{{ $json.output.keyword4 }}\",\n    \"keyword5\": \"{{ $json.output.keyword5 }}\",\n    \"keyword6\": \"{{ $json.output.keyword6 }}\",\n    \"keyword7\": \"{{ $json.output.keyword7 }}\",\n    \"keyword8\": \"{{ $json.output.keyword8 }}\",\n    \"keyword9\": \"{{ $json.output.keyword9 }}\",\n    \"keyword10\": \"{{ $json.output.keyword10 }}\"\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "={{ $('Set Environment Variables').item.json.N8N_WEBHOOK_API_KEY }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4459343c-6649-4cf0-a9e0-ab18676b775d",
      "name": "Send Website Analysis Data to Server",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1520,
        -16
      ],
      "parameters": {
        "url": "={{ $('Set Environment Variables').item.json.BACKEND_API_URL }}api/webhook/n8n ",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"searchId\": \"{{ $('Edit Fields').item.json.searchId }}\",\n  \"stage\": \"website_analysis\",\n  \"websiteData\": [\n    {\n      \"title\": \"{{ $json.title }}\",\n      \"cta\": \"{{ $json.cta }}\",\n      \"website_summary\": \"{{ $json.website_summary }}\",\n      \"target_market_analysis\": \"{{ $json.target_market_analysis }}\",\n      \"preview_image\": \"{{ $('Edit Fields').item.json.preview_image }}\",\n      \"favicon\": \"{{ $('Edit Fields').item.json.favicon }}\"\n    }\n  ]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "={{ $('Set Environment Variables').item.json.N8N_WEBHOOK_API_KEY }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "264e6e25-f7f5-408b-bd8f-d77de3f1b409",
      "name": "Send Conversations for keyword #1 to Server",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2080,
        624
      ],
      "parameters": {
        "url": "={{ $('Set Environment Variables').item.json.BACKEND_API_URL }}api/webhook/n8n",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "=searchId",
              "value": "={{ $('Webhook').item.json.body.searchId }}"
            },
            {
              "name": "=stage",
              "value": "conversations_partial1"
            },
            {
              "name": "=keyword",
              "value": "={{ $('Reddit Posts Keywords Generator').item.json.output.keyword1 }}"
            },
            {
              "name": "passedPosts",
              "value": "={{ $json.content }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "={{ $('Set Environment Variables').item.json.N8N_WEBHOOK_API_KEY }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "f5883372-8e1c-47b5-abaf-afa7888c55fa",
      "name": "Send Conversations for Keyword #2 to Server",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4016,
        96
      ],
      "parameters": {
        "url": "={{ $('Set Environment Variables').item.json.BACKEND_API_URL }}api/webhook/n8n",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "=searchId",
              "value": "={{ $('Webhook').item.json.body.searchId }}"
            },
            {
              "name": "=stage",
              "value": "conversations_partial2"
            },
            {
              "name": "=keyword",
              "value": "={{ $('Reddit Posts Keywords Generator').item.json.output.keyword2 }}"
            },
            {
              "name": "passedPosts",
              "value": "={{ $json.content }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "={{ $('Set Environment Variables').item.json.N8N_WEBHOOK_API_KEY }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "696947ee-4433-41ab-817a-d2aadec0b503",
      "name": "Parse Qualifying Posts",
      "type": "n8n-nodes-base.code",
      "position": [
        1856,
        624
      ],
      "parameters": {
        "jsCode": "// Get the first input item\nconst data = $input.first().json;\n\n// Prepare variables\nlet markdownContent = '';\nlet conversationCount = 1;\nlet hasRelevantConversations = false;\n\n// Loop through all assessments\nfor (let i = 0; i < data.assessment.length; i++) {\n  if (data.assessment[i] === \"relevant\") {\n    hasRelevantConversations = true;\n\n    markdownContent += `# Conversation ${conversationCount}\\n\\n`;\n    markdownContent += `**Subreddit:** r/${data.subreddit[i]}\\n\\n`;\n    markdownContent += `**Title:** ${data.title[i]}\\n\\n`;\n    markdownContent += `**Posted:** ${data.createdAt[i]}\\n\\n`;\n    markdownContent += `**Assessment:** ${data.assessment[i]}\\n\\n`;\n    markdownContent += `## Body\\n${data.body[i]}\\n\\n`;\n    markdownContent += `[View Post](${data.postUrl[i]})\\n\\n`;\n    markdownContent += `---\\n\\n`;\n\n    conversationCount++;\n  }\n}\n\n// Fallback if no relevant conversations exist\nif (!hasRelevantConversations) {\n  markdownContent = 'no_conversations_found';\n}\n\n// Return as a single item\nreturn [\n  {\n    json: {\n      content: markdownContent\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "2e457ed2-0fc0-4b13-bf33-06db31a36153",
      "name": "Parse Qualifying Posts 2",
      "type": "n8n-nodes-base.code",
      "position": [
        3792,
        96
      ],
      "parameters": {
        "jsCode": "// Get the first input item\nconst data = $input.first().json;\n\n// Prepare variables\nlet markdownContent = '';\nlet conversationCount = 1;\nlet hasRelevantConversations = false;\n\n// Loop through all assessments\nfor (let i = 0; i < data.assessment.length; i++) {\n  if (data.assessment[i] === \"relevant\") {\n    hasRelevantConversations = true;\n\n    markdownContent += `# Conversation ${conversationCount}\\n\\n`;\n    markdownContent += `**Subreddit:** r/${data.subreddit[i]}\\n\\n`;\n    markdownContent += `**Title:** ${data.title[i]}\\n\\n`;\n    markdownContent += `**Posted:** ${data.createdAt[i]}\\n\\n`;\n    markdownContent += `**Assessment:** ${data.assessment[i]}\\n\\n`;\n    markdownContent += `## Body\\n${data.body[i]}\\n\\n`;\n    markdownContent += `[View Post](${data.postUrl[i]})\\n\\n`;\n    markdownContent += `---\\n\\n`;\n\n    conversationCount++;\n  }\n}\n\n// If no relevant conversations were found\nif (!hasRelevantConversations) {\n  markdownContent = 'no_conversations_found';\n}\n\n// Return as a single item\nreturn [\n  {\n    json: {\n      content: markdownContent\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e434d3ed-624b-4c29-b7be-0109ce0cce66",
      "name": "Parse Qualifying Posts Final",
      "type": "n8n-nodes-base.code",
      "position": [
        4432,
        672
      ],
      "parameters": {
        "jsCode": "// Get the first input item\nconst data = $input.first().json;\n\n// Prepare an array to hold only the relevant posts\nconst passed_post = [];\n\n// Loop through all assessments\nfor (let i = 0; i < data.assessment.length; i++) {\n  if (data.assessment[i] === \"relevant\") {\n    passed_post.push({\n      subreddit: data.subreddit[i],\n      title: data.title[i],\n      body: data.body[i],\n      postUrl: data.postUrl[i],\n      assessment: data.assessment[i],\n      createdAt: data.createdAt[i]\n    });\n  }\n}\n\n// Return the final filtered list\nreturn [\n  {\n    json: {\n      passed_post\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f5410841-0006-43c8-b531-7d1e2f225aa8",
      "name": "Sanitize & Parse Final Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        3696,
        464
      ],
      "parameters": {
        "jsCode": "// n8n JavaScript Function for Formatting Conversations to Markdown\n// Input: $input.first().json.passed_post (array of keyword groups with conversations)\n// Output: Formatted markdown string\n\nconst data = $input.first().json.passed_post;\n\nif (!data || !Array.isArray(data) || data.length === 0) {\n  return { conversations_final: \"# No conversations available\" };\n}\n\nlet markdown = \"# Filtered Conversations\\n\\n\";\n\n// Iterate through each keyword group (max 8)\ndata.forEach((keywordGroup, keywordIndex) => {\n  if (!keywordGroup || !Array.isArray(keywordGroup) || keywordGroup.length === 0) {\n    return;\n  }\n\n  // Extract keyword from first conversation (assuming it's consistent within group)\n  const keyword = keywordGroup[0]?.keyword || `Keyword Group ${keywordIndex + 1}`;\n  markdown += `## ${keyword}\\n\\n`;\n\n  // Iterate through conversations in this keyword group (max 10)\n  keywordGroup.forEach((conversation, convIndex) => {\n    if (!conversation) return;\n\n    const {\n      subreddit = \"Unknown\",\n      title = \"Untitled\",\n      body = \"\",\n      postUrl = \"#\",\n      createdAt = \"Unknown date\"\n    } = conversation;\n\n    // Format each conversation with ### heading\n    markdown += `### ${title}\\n\\n`;\n    \n    // Metadata section\n    markdown += `**Subreddit:** [r/${subreddit}](https://reddit.com/r/${subreddit})\\n\\n`;\n    markdown += `**Posted:** ${new Date(createdAt).toLocaleDateString()} at ${new Date(createdAt).toLocaleTimeString()}\\n\\n`;\n    \n    // Body content\n    markdown += `**Discussion:**\\n\\n${body}\\n\\n`;\n    \n    // Link to full post\n    markdown += `[View Full Post](${postUrl})\\n\\n`;\n    \n    // Divider between conversations\n    markdown += `---\\n\\n`;\n  });\n\n  // Divider between keyword groups\n  markdown += `\\n\\n`;\n});\n\nreturn { conversations_final: markdown };"
      },
      "typeVersion": 2
    },
    {
      "id": "e70987bf-f0a4-4f81-b1ee-fc618f4c20e3",
      "name": "Send Final Conversations For Keyword #3 to #10 to Server",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4032,
        464
      ],
      "parameters": {
        "url": "={{ $('Set Environment Variables').item.json.BACKEND_API_URL }}api/webhook/n8n",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "=searchId",
              "value": "={{ $('Webhook').item.json.body.searchId }}"
            },
            {
              "name": "=stage",
              "value": "conversations_final"
            },
            {
              "name": "passedPosts",
              "value": "={{ $json.conversations_final }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "={{ $('Set Environment Variables').item.json.N8N_WEBHOOK_API_KEY }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ac1f2acf-4c27-4380-b78f-e41421fd7764",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        -176
      ],
      "parameters": {
        "color": 4,
        "width": 4928,
        "height": 1168,
        "content": "## Reddit Leads Finder N8N Automation"
      },
      "typeVersion": 1
    },
    {
      "id": "80df2ba7-dfb3-4fba-b832-69fef5dd4986",
      "name": "get keyword 3 - 10 For Final Processing",
      "type": "n8n-nodes-base.code",
      "position": [
        2544,
        672
      ],
      "parameters": {
        "jsCode": "// Get the Reddit Posts Keywords Generator node output\nconst keywordData = $('Reddit Posts Keywords Generator').item.json.output;\n\n// Create an array to hold all keywords\nconst keywords = [];\n\n// Loop from keyword2 to keyword10\nfor (let i = 3; i <= 10; i++) {\n  const keywordKey = `keyword${i}`;\n  if (keywordData[keywordKey]) {\n    keywords.push(keywordData[keywordKey]);\n  }\n}\n\n// Return the keywords array\nreturn [\n  {\n    json: {\n      keywords: keywords\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "87f27831-c255-4756-b8a8-552d32efda2e",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -832,
        656
      ],
      "parameters": {
        "width": 560,
        "height": 336,
        "content": "## Resources\n\n1. [Youtube Tutorial]()\n2. [Medium Article Guide]()\n3. [Open Source Github Repo]()\n\n## Contacts for Questions and Work\n\n**Website**: [Leadly Solutions](https://leadlysolutionns.com)\n**Email**: joseph@leadlysolutions.com\n**X/Twitter**: [@juppfy](https://x.com/juppfy)"
      },
      "typeVersion": 1
    },
    {
      "id": "b5beb46d-3236-42f4-b4ae-6cc8afca0926",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -832,
        -176
      ],
      "parameters": {
        "color": 3,
        "width": 560,
        "height": 800,
        "content": "![](https://res.cloudinary.com/dd6vlwblr/image/upload/v1769022321/0_lgiwxy.png)\n## Basic Setup Guide\n**On Set Environment node** get the secret key from [keygen.leadlysolutions.com](https://keygen.leadlysolutions.com) then set it on server/.env if you are using a localhost server or add it to Railway environment dashboard if you are using a Railway server deployment. Then to get the webhook api url, if you are using localhost server, you should use ngrok to make the localhost:3001 available on the internet, so you will enter the ngrok url here, while if you are using the Railway server, it is simple, just open the settings tab, then scroll to public networking and generate the domain then paste it. For both, make sure the url ends with / so that when it is being processed in the respective http nodes here, the url is complete and valid. You can read this medium article for any clarification needed: [Guide](https://docs.n8n.io/workflows/sticky-notes/)\n\nYou can modify the system messages of all ai agents used to adjust the output, but make sure you don't modify the structures output instructions unless you are sure you want to modify the output format. You can explore the github repo, medium article or watch the youtube tutorial in the resources card for any extra info.\n\nYou can also modify the reddit filters to your liking to get desired posts data from the generated keywords"
      },
      "typeVersion": 1
    },
    {
      "id": "f3075513-91af-467f-bf21-6cff561b69fa",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1728,
        208
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "0ce25e86-82df-4678-bbaf-525893203a83",
      "name": "Scrape Product URL and get its content",
      "type": "@mendable/n8n-nodes-firecrawl.firecrawl",
      "position": [
        288,
        -16
      ],
      "parameters": {
        "url": "={{ $('Webhook').item.json.body.productUrl }}",
        "parsers": [
          "pdf"
        ],
        "operation": "scrape",
        "scrapeOptions": {
          "options": {
            "formats": {
              "format": [
                {}
              ]
            },
            "headers": {}
          }
        },
        "requestOptions": {}
      },
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Parse Qualifying Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge3": {
      "main": [
        [
          {
            "node": "Parse Qualifying Posts 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge5": {
      "main": [
        [
          {
            "node": "Parse Qualifying Posts Final",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Set Environment Variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Aggregate3": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate5": {
      "main": [
        [
          {
            "node": "Merge3",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Aggregate6": {
      "main": [
        [
          {
            "node": "Merge3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate9": {
      "main": [
        [
          {
            "node": "Merge5",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Split Out1": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate10": {
      "main": [
        [
          {
            "node": "Merge5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate11": {
      "main": [
        [
          {
            "node": "Sanitize & Parse Final Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Sanitize JSON Values",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean results": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          },
          {
            "node": "Posts Relevance AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean results2": {
      "main": [
        [
          {
            "node": "Aggregate5",
            "type": "main",
            "index": 0
          },
          {
            "node": "Posts Relevance AI Agent2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean results4": {
      "main": [
        [
          {
            "node": "Aggregate9",
            "type": "main",
            "index": 0
          },
          {
            "node": "Posts Relevance AI Agent4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items1": {
      "main": [
        [
          {
            "node": "Aggregate11",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Search for Posts (Keyword/Phrase)4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sanitize Results": {
      "main": [
        [
          {
            "node": "Analyze Product URL Scrape",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Reddit Posts Keywords Generator",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze Product URL Scrape",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model2": {
      "ai_languageModel": [
        [
          {
            "node": "Posts Relevance AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model3": {
      "ai_languageModel": [
        [
          {
            "node": "Posts Relevance AI Agent2",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model5": {
      "ai_languageModel": [
        [
          {
            "node": "Posts Relevance AI Agent4",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Sanitize JSON Values": {
      "main": [
        [
          {
            "node": "Send Website Analysis Data to Server",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Qualifying Posts": {
      "main": [
        [
          {
            "node": "Send Conversations for keyword #1 to Server",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send keywords to Server": {
      "main": [
        [
          {
            "node": "Search for Posts (Keyword/Phrase)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Qualifying Posts 2": {
      "main": [
        [
          {
            "node": "Send Conversations for Keyword #2 to Server",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Posts Relevance AI Agent": {
      "main": [
        [
          {
            "node": "Aggregate3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Reddit Posts Keywords Generator",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Posts Relevance AI Agent2": {
      "main": [
        [
          {
            "node": "Aggregate6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Posts Relevance AI Agent4": {
      "main": [
        [
          {
            "node": "Aggregate10",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Environment Variables": {
      "main": [
        [
          {
            "node": "Scrape Product URL and get its content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser1": {
      "ai_outputParser": [
        [
          {
            "node": "Posts Relevance AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser4": {
      "ai_outputParser": [
        [
          {
            "node": "Analyze Product URL Scrape",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser5": {
      "ai_outputParser": [
        [
          {
            "node": "Posts Relevance AI Agent2",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser7": {
      "ai_outputParser": [
        [
          {
            "node": "Posts Relevance AI Agent4",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Product URL Scrape": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Qualifying Posts Final": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sanitize & Parse Final Payload": {
      "main": [
        [
          {
            "node": "Send Final Conversations For Keyword #3 to #10 to Server",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Reddit Posts Keywords Generator": {
      "main": [
        [
          {
            "node": "Send keywords to Server",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search for Posts (Keyword/Phrase)": {
      "main": [
        [
          {
            "node": "Clean results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search for Posts (Keyword/Phrase)2": {
      "main": [
        [
          {
            "node": "Clean results2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search for Posts (Keyword/Phrase)4": {
      "main": [
        [
          {
            "node": "Clean results4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Website Analysis Data to Server": {
      "main": [
        [
          {
            "node": "Reddit Posts Keywords Generator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Product URL and get its content": {
      "main": [
        [
          {
            "node": "Sanitize Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get keyword 3 - 10 For Final Processing": {
      "main": [
        [
          {
            "node": "Split Out1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Conversations for Keyword #2 to Server": {
      "main": [
        [
          {
            "node": "get keyword 3 - 10 For Final Processing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Conversations for keyword #1 to Server": {
      "main": [
        [
          {
            "node": "Search for Posts (Keyword/Phrase)2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Production-ready Reddit lead generation system with progressive data loading for optimal UX. This workflow integrates with a web frontend, sending results in real-time as they're processed instead of waiting for everything to complete.

Source: https://n8n.io/workflows/12884/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow automatically processes new free-trial / lead sign-ups in real time: Catches a webhook from any source (Webflow form, Intercom, custom agent, etc.) Filters out personal / disposable / .e

Output Parser Structured, Agent, HTTP Request +7
AI & RAG

⏺ 🚀 How it works

Agent, Anthropic Chat, Output Parser Structured +6
AI & RAG

Stop reading job listings that aren't a fit. This workflow automatically crawls five major job boards (LinkedIn, Indeed, WeAreDevelopers, Stepstone, and Xing) and scores every listing against your per

OpenAI Chat, Agent, @Mendable/N8N Nodes Firecrawl +3
AI & RAG

🧠 Gwen – The AI Voice Marketing Agent Gwen is your intelligent voice-powered marketing assistant built in n8n. She combines the power of OpenAI, ElevenLabs, and automation workflows to handle content

Tool Workflow, Memory Buffer Window, Agent +10
AI & RAG

Tired of grinding out YouTube content? This n8n workflow turns AI into your personal video factory—creating engaging, faceless shorts on autopilot. Perfect for creators, marketers, or side-hustlers lo

HTTP Request, Google Drive, Google Sheets +6