{
  "id": "hkUBomZwuryHuH6n",
  "name": "Automated Brand DNA Generator Using JotForm, Google Search, AI Extraction & Notion",
  "tags": [],
  "nodes": [
    {
      "id": "6376bb20-06e3-4ae3-9d61-28ba339555d0",
      "name": "JotForm Trigger",
      "type": "n8n-nodes-base.jotFormTrigger",
      "position": [
        1296,
        272
      ],
      "parameters": {
        "form": "="
      },
      "credentials": {
        "jotFormApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c022594f-0f11-4b01-9422-5c44369f8b46",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        1504,
        272
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nreturn items.map(item => {\n  let website = item.json[\"Company Website\"] || \"\";\n\n  // Clean whitespace\n  website = website.trim();\n\n  // Add protocol if missing\n  if (!website.startsWith(\"http://\") && !website.startsWith(\"https://\")) {\n    website = \"https://\" + website;\n  }\n\n  try {\n    const url = new URL(website);\n    let domain = url.hostname.replace(/^www\\./, \"\"); // remove \"www.\"\n\n    return {\n      json: {\n        ...item.json,\n        Domain: domain\n      }\n    };\n  } catch (e) {\n    // If not a valid URL, fallback to plain string\n    const fallbackDomain = website\n      .replace(/^https?:\\/\\//, \"\")\n      .replace(/^www\\./, \"\")\n      .split(\"/\")[0];\n\n    return {\n      json: {\n        ...item.json,\n        Domain: fallbackDomain\n      }\n    };\n  }\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "606c9887-c104-4f5c-8b44-f21f55db5f06",
      "name": "Google search",
      "type": "n8n-nodes-serpapi.serpApi",
      "position": [
        1712,
        272
      ],
      "parameters": {
        "q": "=site:{{ $json.Domain }}",
        "requestOptions": {},
        "additionalFields": {}
      },
      "typeVersion": 1
    },
    {
      "id": "c96ed505-2b84-4bf3-8e38-e9701f6f7886",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2544,
        576
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "ab2ba7f5-9d82-4c06-9350-132522dfbf79",
      "name": "WebpageContentExtractor",
      "type": "n8n-nodes-webpage-content-extractor.webpageContentExtractor",
      "notes": "data not found",
      "onError": "continueRegularOutput",
      "position": [
        3104,
        576
      ],
      "parameters": {
        "html": "={{ $json.data }}"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "7c4cdb90-cb54-4893-9e27-8002af3c4320",
      "name": "Information Extractor",
      "type": "@n8n/n8n-nodes-langchain.informationExtractor",
      "position": [
        3328,
        576
      ],
      "parameters": {
        "text": "=Company name : {{ $('JotForm Trigger').item.json['Company Name'] }}\nWebpage Content : {{ $json.textContent }}",
        "options": {
          "systemPromptTemplate": "=You are an expert information extraction algorithm.\nYour task is to extract only essential and relevant information about the company named \"{{ $('JotForm Trigger').item.json['Company Name'] }}\" and its context within the article text.\nIf a field or value is not available, omit it completely. Do not fabricate or infer information.\nReturn only a clean and valid JSON object following the provided schema."
        },
        "schemaType": "fromJson",
        "jsonSchemaExample": "{\n  \"companyName\":\"11x.ai\",\n  \"relatedToBrand\": \"reply.io\",\n  \"isRelated\": true,\n  \"relationType\": \"positioning\",\n  \"reason\": \"The article mentions 11x as an AI sales automation platform and includes a demo link.\",\n  \"articleGoal\": \"To compare UberConference alternatives and highlight 11x's position within the sales tools ecosystem.\",\n  \"excerpt\": \"Transform your revenue team with digital AI workers that execute, learn, and optimize.\",\n  \"summary\": \"The article introduces 11x as an AI-driven solution for automating sales and prospect management.\",\n  \"keyPoints\": [\n    \"11x positions itself as an AI sales automation platform.\",\n    \"The article compares various meeting and communication tools.\",\n    \"Includes a demo link to showcase 11x\u2019s capabilities.\",\n    \"Focuses on digital AI workers improving sales efficiency.\"\n  ]\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "e0a12b7c-151e-4b52-ae88-06630ad4348a",
      "name": "OpenRouter Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        3328,
        800
      ],
      "parameters": {
        "model": "google/gemini-2.0-flash-exp:free",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "4ac523fc-0ddf-42a0-b797-7c050bbd9b9e",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2128,
        272
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "9aae62eb-881d-4ba0-93ee-4ddf2624b6a1",
      "name": "Information Extractor1",
      "type": "@n8n/n8n-nodes-langchain.informationExtractor",
      "position": [
        2752,
        -48
      ],
      "parameters": {
        "text": "=companyName : {{ $json.companyName }}\nrelatedToBrand : {{ $json.relatedToBrand }}\nrelationType: {{ $json.relationType }}\nreason : {{ $json.reason }}\narticleGoal : {{ $json.articleGoal }}\nexcerpt : {{ $json.excerpt }}\nsummary : {{ $json.summary }}\nkeyPoints : {{ $json.keyPoints }}",
        "options": {
          "systemPromptTemplate": "=You are a brand strategist.\nMerge multiple extraction results into one concise Brand DNA for the company named \"{{ $json.relatedToBrand }}\".\nReturn STRICT JSON only, no extra text. Be factual; do not invent details.\nConsolidate duplicates, remove overlap, and keep language neutral and concise.\nIf a field has no evidence, omit it entirely.\n"
        },
        "schemaType": "fromJson",
        "jsonSchemaExample": "{\n  \"companyName\":\"\",\n  \"companyDescription\": \"\",\n  \"idealCustomerProfile\": [],\n  \"painPoints\": [],\n  \"valueProposition\": [],\n  \"proofPoints\": [],\n  \"reasonsToOutreach\": [],\n  \"outreachChannels\": [],\n  \"suggestedKeywords\": [],\n  \"brandTone\": \"\"\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "8df1f5a1-927a-4397-bc4a-60d261d3bf12",
      "name": "OpenRouter Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        2752,
        112
      ],
      "parameters": {
        "model": "google/gemini-2.0-flash-exp:free",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "9b4fde9e-5d58-4762-8dc2-b53eff25e1ca",
      "name": "Merge Data",
      "type": "n8n-nodes-base.code",
      "position": [
        2544,
        -48
      ],
      "parameters": {
        "jsCode": "// n8n Code node \u2014 Simple Combine to One\n// Combine multiple extractor results into one object without complex heuristics.\n\nconst items = $input.all();\n\n// --- CONFIG ---\nconst AS_ARRAYS = true;   // true: save as array; false: join string \" | \"\nconst JOINER = \" | \";     // separator when AS_ARRAYS=false\n\n// Fields processed as \"list\" (will be merged & deduplicated)\nconst LIST_FIELDS = new Set([\n  \"keyPoints\",        // array\n  \"relationType\",     // can appear in various forms \u2192 make it a list\n  \"reason\",           // reasons can be more than one\n  \"articleGoal\",      // goals can vary between pages\n  \"excerpt\",          // can save all excerpts (or take first in SCALAR_PREFERS_FIRST)\n  \"summary\"           // can save all summaries (or take first in SCALAR_PREFERS_FIRST)\n]);\n\n// If you want some fields to remain scalar (take first), put them here:\nconst SCALAR_PREFERS_FIRST = new Set([\n  \"relatedToBrand\"    // take the first non-empty one\n]);\n\n// Helper\nconst norm = (v) => (v == null ? \"\" : String(v).trim());\nconst toArr = (v) => Array.isArray(v) ? v : (v == null ? [] : [v]);\nconst dedupe = (arr) => {\n  const seen = new Set(); const out = [];\n  for (const x of arr) {\n    const s = norm(x);\n    const k = s.toLowerCase();\n    if (s && !seen.has(k)) { seen.add(k); out.push(s); }\n  }\n  return out;\n};\n\n// Extract record from various forms\nconst extractRecord = (it) => {\n  if (it?.json?.output && typeof it.json.output === \"object\") return it.json.output;\n  if (it?.json && typeof it.json === \"object\") return it.json;\n  return {};\n};\n\n// Collect all records\nconst records = items.map(extractRecord);\n\n// Initial combination\nconst combined = {};\nlet anyRelatedTrue = false;\n\n// Loop to combine\nfor (const rec of records) {\n  for (const [k, v] of Object.entries(rec)) {\n    if (k === \"isRelated\") {\n      if (v === true || v === \"true\") anyRelatedTrue = true;\n      continue;\n    }\n\n    // If field is set for scalar-first \u2192 save only the first one\n    if (SCALAR_PREFERS_FIRST.has(k)) {\n      if (!combined[k]) {\n        const val = Array.isArray(v) ? v.find(x => norm(x)) : v;\n        if (norm(val)) combined[k] = norm(val);\n      }\n      continue;\n    }\n\n    // Otherwise, treat as list so all values are included\n    const list = toArr(v);\n    if (!combined[k]) combined[k] = [];\n    combined[k].push(...list);\n  }\n}\n\n// Dedupe for all fields that are lists\nfor (const k of Object.keys(combined)) {\n  if (Array.isArray(combined[k]) || LIST_FIELDS.has(k)) {\n    combined[k] = dedupe(toArr(combined[k]));\n  }\n}\n\n// Set boolean isRelated\ncombined.isRelated = anyRelatedTrue;\n\n// Final output:\n// - If AS_ARRAYS=false \u2192 join lists into string with JOINER\nif (!AS_ARRAYS) {\n  for (const [k, v] of Object.entries(combined)) {\n    if (Array.isArray(v)) combined[k] = v.join(JOINER);\n  }\n}\n\n// Clean empty fields\nfor (const k of Object.keys(combined)) {\n  const v = combined[k];\n  if (Array.isArray(v) && v.length === 0) delete combined[k];\n  if (typeof v === \"string\" && !v.trim()) delete combined[k];\n}\n\nreturn [{ json: combined }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "8778a112-c980-4c2f-a14c-ec98d8152a75",
      "name": "Code in JavaScript2",
      "type": "n8n-nodes-base.code",
      "position": [
        3072,
        -48
      ],
      "parameters": {
        "jsCode": "// n8n Code Node \u2014 Format per-section (strings) for Notion blocks UI\n// Input: items[0].json.output\n// Output: multiple string fields: h1, h2_xxx, p_xxx (each <= ~1900 chars)\n\nconst item = $input.item;\nconst d = item.json.output || item.json || {};\n\n// Safe content limit per Notion block (~2000 chars, using 1900)\nconst LIMIT = 1900;\n\nconst clip = (s) => String(s ?? '').slice(0, LIMIT).trim();\n\n// Array \u2192 bullets in one paragraph (1 Notion block, multiline)\nfunction bulletsParagraph(arr) {\n  if (!Array.isArray(arr) || !arr.length) return '- (none)';\n  const lines = arr\n    .filter(x => x != null && String(x).trim() !== '')\n    .map(x => `\u2022 ${String(x).replace(/\\s+/g, ' ').trim()}`);\n  return clip(lines.join('\\n'));\n}\n\n// Scalar \u2192 single string\nconst scalar = (s) => {\n  const v = (s == null || String(s).trim() === '') ? '- (none)' : String(s);\n  return clip(v);\n};\n\n// Get company name for H1 (layered fallback)\nconst companyName =\n  d.companyName ||\n  d.company ||\n  item.json.companyName ||\n  item.json['Company Name'] ||\n  'Unknown Company';\n\n// Arrange all sections as separate strings\nconst output = {\n  // Main heading = Company Name\n  h1: scalar(companyName),\n\n  // Company Description\n  h2_companyDescription: 'Company Description',\n  p_companyDescription: scalar(d.companyDescription),\n\n  // ICP\n  h2_icp: 'Ideal Customer Profile (ICP)',\n  p_icp: bulletsParagraph(d.idealCustomerProfile),\n\n  // Pain Points\n  h2_painPoints: 'Pain Points',\n  p_painPoints: bulletsParagraph(d.painPoints),\n\n  // Value Proposition\n  h2_valueProposition: 'Value Proposition',\n  p_valueProposition: bulletsParagraph(d.valueProposition),\n\n  // Proof Points\n  h2_proofPoints: 'Proof Points',\n  p_proofPoints: bulletsParagraph(d.proofPoints),\n\n  // Reasons to Outreach\n  h2_reasonsToOutreach: 'Reasons to Outreach',\n  p_reasonsToOutreach: bulletsParagraph(d.reasonsToOutreach),\n\n  // Outreach Channels\n  h2_outreachChannels: 'Outreach Channels',\n  p_outreachChannels: bulletsParagraph(d.outreachChannels),\n\n  // Suggested Keywords\n  h2_suggestedKeywords: 'Suggested Keywords',\n  p_suggestedKeywords: bulletsParagraph(d.suggestedKeywords),\n\n  // Brand Tone\n  h2_brandTone: 'Brand Tone',\n  p_brandTone: scalar(d.brandTone),\n};\n\nreturn [{ json: output }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e224592f-fecb-414e-a598-e3bdfc326afe",
      "name": "Create a database page",
      "type": "n8n-nodes-base.notion",
      "position": [
        3280,
        -48
      ],
      "parameters": {
        "title": "={{ $json.h1 }}",
        "blockUi": {
          "blockValues": [
            {
              "type": "heading_2",
              "textContent": "={{ $json.h2_companyDescription }}"
            },
            {
              "textContent": "={{ $json.p_companyDescription }}"
            },
            {
              "type": "heading_2",
              "textContent": "={{ $json.h2_icp }}"
            },
            {
              "textContent": "={{ $json.p_icp }}"
            },
            {
              "type": "heading_2",
              "textContent": "={{ $json.h2_painPoints }}"
            },
            {
              "textContent": "={{ $json.p_painPoints }}"
            },
            {
              "type": "heading_2",
              "textContent": "={{ $json.h2_valueProposition }}"
            },
            {
              "textContent": "={{ $json.p_valueProposition }}"
            },
            {
              "type": "heading_2",
              "textContent": "={{ $json.h2_proofPoints }}"
            },
            {
              "textContent": "={{ $json.p_proofPoints }}"
            },
            {
              "type": "heading_2",
              "textContent": "={{ $json.h2_reasonsToOutreach }}"
            },
            {
              "textContent": "={{ $json.p_reasonsToOutreach }}"
            },
            {
              "type": "heading_2",
              "textContent": "={{ $json.h2_outreachChannels }}"
            },
            {
              "textContent": "={{ $json.p_outreachChannels }}"
            },
            {
              "type": "heading_2",
              "textContent": "={{ $json.h2_suggestedKeywords }}"
            },
            {
              "textContent": "={{ $json.p_suggestedKeywords }}"
            },
            {
              "type": "heading_2",
              "textContent": "={{ $json.h2_brandTone }}"
            },
            {
              "textContent": "={{ $json.p_brandTone }}"
            }
          ]
        },
        "options": {},
        "resource": "databasePage",
        "databaseId": "="
      },
      "typeVersion": 2.2
    },
    {
      "id": "461dc0fa-29ed-4162-8b44-44678b3405a9",
      "name": "Code in JavaScript1",
      "type": "n8n-nodes-base.code",
      "position": [
        2752,
        576
      ],
      "parameters": {
        "jsCode": "// n8n Code Node \u2014 Simple HTML \u2192 Clean Text Array\n// Output format: [{ \"data\": \"clean text\" }]\n\nconst items = $input.all();\n\n// Helper: remove all HTML tags, comments, and script/style\nfunction cleanHTML(html = '') {\n  return html\n    .replace(/<!--[\\s\\S]*?-->/g, ' ')                     // comments\n    .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, ' ') // script\n    .replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, ' ')   // style\n    .replace(/<noscript\\b[^<]*(?:(?!<\\/noscript>)<[^<]*)*<\\/noscript>/gi, ' ')\n    .replace(/<\\/?(svg|math)[\\s\\S]*?<\\/\\1>/gi, ' ')\n    .replace(/<[^>]+>/g, ' ') // remove all tags\n    .replace(/&nbsp;/gi, ' ')\n    .replace(/&amp;/gi, '&')\n    .replace(/&lt;/gi, '<')\n    .replace(/&gt;/gi, '>')\n    .replace(/&quot;/gi, '\"')\n    .replace(/&#39;/gi, \"'\")\n    .replace(/\\s+/g, ' ')\n    .trim();\n}\n\n// Get html from several possible keys\nfunction pickHtml(json) {\n  const keys = ['data', 'html', 'body', 'content', 'text'];\n  for (const k of keys) {\n    if (typeof json?.[k] === 'string' && json[k].trim()) return json[k];\n  }\n  if (typeof json?.output === 'object') {\n    for (const k of keys) {\n      if (typeof json.output[k] === 'string' && json.output[k].trim()) return json.output[k];\n    }\n  }\n  return '';\n}\n\nreturn items.map((item) => {\n  const raw = pickHtml(item.json) || '';\n  const cleaned = cleanHTML(raw);\n  return { json: { data: cleaned } };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c0a0e828-12c2-4024-b2ce-3df29f0b424b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        -176
      ],
      "parameters": {
        "width": 620,
        "height": 1288,
        "content": "# Automated Brand DNA Generator Using JotForm, Google Search, AI Extraction & Notion\n\nThe Brand DNA Generator workflow automatically scans and analyzes online content to build a company\u2019s Brand DNA profile.  It starts with input from a form, then crawls the company\u2019s website and Google search results to gather relevant information. Using AI-powered extraction, the system identifies insights such as value propositions, ideal customer profiles (ICP), pain points, proof points, brand tone, and more.  All results are neatly formatted and automatically saved to a Notion database as a structured Brand DNA report, eliminating the need for manual research.\n\n## \ud83d\udee0\ufe0f Key Features\n- Automated data capture, collects company data directly from form submissions and Google search results.  \n- Uses AI-powered insight extraction with LLMs to extract and summarize brand-related information from website content.  \n- Fetches clean text from multiple web pages using HTTP requests and a content extractor.  \n- Merges extracted data from multiple sources into a single Brand DNA JSON structure.  \n- Automatically creates a new page in Notion with formatted sections (headings, paragraphs, and bullet points).  \n- Handles parsing failures and processes multiple pages efficiently in batches.\n\n## \ud83d\udd27 Requirements\n- JotForm API Key, to capture company data from form submissions.  \n- SerpAPI Key, to perform automated Google searches.  \n- OpenRouter / LLM API, for AI-based language understanding and information extraction.  \n- Notion Integration Token & Database ID, to save the final Brand DNA report to Notion.\n\n## \ud83e\udde9 Setup Instructions\n1. Connect your JotForm account and select the form containing the fields Company Name and Company Website.  \n2. Add your SerpAPI Key.  \n3. Configure the AI model using OpenRouter or LLM.  \n4. Enter your Notion credentials and specify the databaseId in the Create a Database Page node.  \n5. Customize the prompt in the Information Extractor node to modify the tone or structure of AI analysis (Optional).  \n6. Activate the workflow, then submit data through the JotForm to test automatic generation and Notion integration.\n\n## \ud83d\udca1 Final Output  \nA complete Brand DNA Report containing:\n- Company Description  \n- Ideal Customer Profile  \n- Pain Points  \n- Value Proposition  \n- Proof Points  \n- Brand Tone  \n- Suggested Keywords  \nAll generated automatically from the company\u2019s online presence and stored in Notion with no manual input required."
      },
      "typeVersion": 1
    },
    {
      "id": "810cd05b-cd23-4af0-a5ec-5ebccb3d9e3e",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        112
      ],
      "parameters": {
        "color": 2,
        "width": 384,
        "height": 304,
        "content": "- Starts the workflow when a new form submission is received from JotForm.\n- Cleans and standardizes the submitted website URL."
      },
      "typeVersion": 1
    },
    {
      "id": "95e9e2a4-2469-48df-85f3-11ae0110b139",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1680,
        112
      ],
      "parameters": {
        "color": 3,
        "width": 368,
        "height": 304,
        "content": "- Automatically retrieves search results related to the company\u2019s domain.\n- Extracts and cleans URLs from the SerpAPI search results."
      },
      "typeVersion": 1
    },
    {
      "id": "2ea4072f-acf6-4c7f-98af-abd531ab0a68",
      "name": "Set url",
      "type": "n8n-nodes-base.code",
      "position": [
        1920,
        272
      ],
      "parameters": {
        "jsCode": "// Get all items from previous node (each item = one SerpAPI result)\nconst items = $input.all();\nconst out = [];\n\nfor (const item of items) {\n  const data = item.json || {};\n  const results = Array.isArray(data.organic_results) ? data.organic_results : [];\n\n  // Collect links + fallback from redirect_link?url=...\n  const urls = results.map(r => {\n    if (r.link) return r.link;\n    if (r.redirect_link) {\n      try {\n        const u = new URL(r.redirect_link);\n        const real = u.searchParams.get('url');\n        if (real) return real;\n      } catch (e) {}\n    }\n    return null;\n  }).filter(Boolean);\n\n  // Dedupe\n  const unique = [...new Set(urls)];\n\n  // Output one item per URL (include useful metadata)\n  for (const r of results) {\n    // Match parsed URL with r.link/redirect_link\n    let resolved = r.link;\n    if (!resolved && r.redirect_link) {\n      try {\n        const u = new URL(r.redirect_link);\n        const real = u.searchParams.get('url');\n        if (real) resolved = real;\n      } catch (e) {}\n    }\n    if (resolved && unique.includes(resolved)) {\n      out.push({\n        json: {\n          url: resolved,\n          position: r.position ?? null,\n          title: r.title ?? null,\n          displayed_link: r.displayed_link ?? null,\n          source: r.source ?? null,\n          date: r.date ?? null\n        }\n      });\n    }\n  }\n}\n\n// If no organic_results, return empty info to keep flow running\nreturn out.length ? out : [{ json: { url: null, note: 'No organic_results found' } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "253be165-bc96-4178-8842-04a165dd012f",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2512,
        -272
      ],
      "parameters": {
        "color": 4,
        "width": 496,
        "height": 528,
        "content": "- Combine multiple extraction results (from many pages) into a single deduplicated record.\n- Consolidate and synthesize extracted article-level data into a Brand DNA candidate.\n- Provide the language model (LLM) backend used by the Information Extractor node."
      },
      "typeVersion": 1
    },
    {
      "id": "36e117cb-214d-4d44-b012-3bdc82c5f01e",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3040,
        -272
      ],
      "parameters": {
        "color": 5,
        "width": 496,
        "height": 528,
        "content": "- Format consolidated Brand DNA JSON into string fields suitable for Notion blocks.\n- Persist the formatted Brand DNA into a Notion database as a new page."
      },
      "typeVersion": 1
    },
    {
      "id": "9efd3a0a-5a04-42b3-abbe-29cd8e878fa6",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2512,
        352
      ],
      "parameters": {
        "color": 4,
        "width": 496,
        "height": 528,
        "content": "- Fetches raw HTML content from a given website URL.\n- Clean and extract readable text from raw HTML."
      },
      "typeVersion": 1
    },
    {
      "id": "6cc1c8d7-7d7b-470f-86d2-542a7443e879",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3056,
        352
      ],
      "parameters": {
        "color": 5,
        "width": 576,
        "height": 608,
        "content": "- Extracts structured and readable content from raw HTML.\n- Uses AI to extract structured company-related information from the article."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "a4b127eb-22d0-4a63-88e7-2ff617914cfa",
  "connections": {
    "Set url": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Data": {
      "main": [
        [
          {
            "node": "Information Extractor1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Code in JavaScript1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google search": {
      "main": [
        [
          {
            "node": "Set url",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "JotForm Trigger": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Merge Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Google search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript1": {
      "main": [
        [
          {
            "node": "WebpageContentExtractor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript2": {
      "main": [
        [
          {
            "node": "Create a database page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Information Extractor": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Information Extractor",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Information Extractor1": {
      "main": [
        [
          {
            "node": "Code in JavaScript2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Information Extractor1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "WebpageContentExtractor": {
      "main": [
        [
          {
            "node": "Information Extractor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}