{
  "id": "qthXGkJCm1YAAQpW",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI SEO Readability Audit: Check Website Friendliness for LLMs",
  "tags": [
    {
      "id": "JkpR8IEIpOrc2x6l",
      "name": "Leonard van Hemert",
      "createdAt": "2025-05-17T14:14:16.649Z",
      "updatedAt": "2025-05-17T14:14:16.649Z"
    }
  ],
  "nodes": [
    {
      "id": "ea4c49eb-5a9d-4de9-acc7-3eef90b11f29",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        -340,
        -140
      ],
      "parameters": {
        "public": true,
        "options": {
          "title": "\ud83d\ude80 AI SEO Readability Checker",
          "subtitle": "Test how AI-friendly your website is for search engines like ChatGPT & Perplexity \u2013 built by [Leonard van Hemert](https://nl.linkedin.com/in/leonard-van-hemert)",
          "responseMode": "lastNode",
          "inputPlaceholder": "https://example.com"
        },
        "initialMessages": "Hi! \ud83d\udc4b  \nSend your website link and I\u2019ll check how AI-friendly it is for tools like ChatGPT and Perplexity. Let\u2019s go! \ud83d\ude80"
      },
      "typeVersion": 1.1
    },
    {
      "id": "0ede3abb-3cad-4e9a-bc8c-79d8eac06fe6",
      "name": "Get HTML from Website",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        100,
        -140
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {
          "timeout": 10000
        },
        "jsonHeaders": "{\n  \"User-Agent\": \"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\",\n  \"Accept-Language\": \"nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7\"\n}",
        "sendHeaders": true,
        "specifyHeaders": "json"
      },
      "retryOnFail": true,
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "96d8c97a-8d7b-41fb-a109-d56e34d7dff1",
      "name": "Sanitize Website URL",
      "type": "n8n-nodes-base.code",
      "position": [
        -120,
        -140
      ],
      "parameters": {
        "jsCode": "return [\n  {\n    json: {\n      url: (() => {\n        let input = $json.chatInput.trim().toLowerCase();\n        if (!input.startsWith('http')) input = 'https://' + input;\n        return input;\n      })()\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "2b8a702e-b141-4f71-9e8f-2caa69cfad80",
      "name": "Extract HTML Features",
      "type": "n8n-nodes-base.code",
      "position": [
        320,
        -140
      ],
      "parameters": {
        "jsCode": "const html = $json.data || '';\n\n// Remove scripts, styles, and extract visible text\nconst cleanedText = html\n  .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n  .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n  .replace(/<[^>]*>/g, '') // strip all HTML tags\n  .replace(/\\s+/g, ' ')\n  .trim();\n\n// Preview: first 400 chars of visible content\nconst previewText = cleanedText.slice(0, 400);\n\n// Lowercased text for language-agnostic JS block detection\nconst lowerText = cleanedText.toLowerCase();\n\n// Common JS-related blocking messages (EN + NL + DE)\nconst jsBlockIndicators = [\n  'enable javascript',\n  'javascript is required',\n  'please enable javascript',\n  'javascript moet ingeschakeld zijn',\n  'schakel javascript in',\n  'javascript erforderlich'\n];\n\n// Scan for any of the indicators\nconst jsWarningDetected = jsBlockIndicators.some(phrase => lowerText.includes(phrase));\n\nreturn [\n  {\n    json: {\n      visibleTextLength: cleanedText.length,\n      previewText,\n      hasH1: /<h1[\\s>]/i.test(html),\n      hasH2: /<h2[\\s>]/i.test(html),\n      hasH3: /<h3[\\s>]/i.test(html),\n      hasMetaDescription: /<meta[^>]+name=[\"']description[\"']/i.test(html),\n      hasOpenGraph: /<meta[^>]+property=[\"']og:/i.test(html),\n      hasStructuredData: /<script[^>]*type=[\"']application\\/ld\\+json[\"']/i.test(html),\n      hasNoscript: /<noscript[\\s>]/i.test(html),\n      jsWarning: jsWarningDetected,\n      robotsTxt: $('Sanitize Website URL').first().json.url.replace(/\\/$/, '') + '/robots.txt'\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "58591741-7896-4f0f-a5d6-a16efccdf4a3",
      "name": "AI SEO Analysis",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        540,
        -140
      ],
      "parameters": {
        "text": "=You are an expert in AI SEO analysis and AI search engine accessibility.\n\nYou are evaluating a website\u2019s readability for LLM-based tools like ChatGPT, Perplexity, and Google AI Overviews. The website's raw HTML was fetched *without JavaScript execution*, simulating how LLMs typically see pages.\n\n---\n\n### \ud83e\uddfe Technical Scan Summary\n\n**Visible content (no JS):**\n- Text length: {{ $json.visibleTextLength }} characters\n- Preview: \"{{ $json.previewText }}\"\n\n**Detected features:**\n- Structured Data (JSON-LD): {{ $json.hasStructuredData }}\n- Meta Description: {{ $json.hasMetaDescription }}\n- Open Graph Metadata: {{ $json.hasOpenGraph }}\n- Headings: H1: {{ $json.hasH1 }}, H2: {{ $json.hasH2 }}, H3: {{ $json.hasH3 }}\n- `<noscript>` fallback present: {{ $json.hasNoscript }}\n- JavaScript-blocking warning found: {{ $json.jsWarning }}\n\n---\n\n### \ud83c\udfaf Your task:\nEvaluate the AI-readability of this website and return:\n\n1. An **AI Readability Score (0\u201310)**\n2. A **brief summary** of the current state (2\u20134 sentences)\n3. Up to **5 actionable recommendations** to improve visibility and accessibility for AI search engines\n\n\ud83d\udca1 If the text length is below 300 or the `JavaScript-blocking warning found` is true, clearly state that the site may not be accessible to LLMs due to JavaScript dependency.\n\n\u26a0\ufe0f **Important:**\nYou must also **tell the user** to check their `robots.txt` file manually, and provide this exact clickable link:  \n\ud83d\udc49 [{{ $json.robotsTxt }}]({{ $json.robotsTxt }})  \nExplain they must ensure bots like `GPTBot`, `ChatGPT-User`, and `Google-Extended` are **not blocked**.\n\nDo not perform this check yourself \u2014 just inform the user to do it.\n\n---\n\n\ud83c\udf81 Format your response like this:\n\n**Score:** x/10  \n**Summary:** ...  \n**Recommendations:**\n- ...\n- Check your robots.txt file at [{{ $json.robotsTxt }}]({{ $json.robotsTxt }}) to ensure AI bots are allowed.",
        "promptType": "define"
      },
      "typeVersion": 1.6
    },
    {
      "id": "080e40e2-bfb3-42df-8f92-ac1379135aad",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -380,
        20
      ],
      "parameters": {
        "color": 4,
        "width": 740,
        "height": 700,
        "content": "# \ud83d\ude80 AI SEO \uac00\ub3c5\uc131 \uac10\uc0ac \uc6cc\ud06c\ud50c\ub85c\uc6b0\n\n**\ubaa9\uc801:** \uc774 \uc6cc\ud06c\ud50c\ub85c\uc6b0\ub294 \uc6f9\uc0ac\uc774\ud2b8\uc758 HTML\uc744 \ubd84\uc11d\ud558\uc5ec ChatGPT \ubc0f Perplexity\uc640 \uac19\uc740 \ub300\ud615 \uc5b8\uc5b4 \ubaa8\ub378(LLM)\uc774 \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc2e4\ud589\ud558\uc9c0 \uc54a\uace0 \ud06c\ub864\ub9c1\ud560 \ub54c\uc758 \uac00\ub3c5\uc131\uacfc \uc811\uadfc\uc131\uc744 \ud3c9\uac00\ud569\ub2c8\ub2e4.\n\n**\uc791\ub3d9 \ubc29\uc2dd:**\n1.  \ucc44\ud305\uc5d0 \uc6f9\uc0ac\uc774\ud2b8 URL\uc744 \uc785\ub825\ud569\ub2c8\ub2e4.\n2.  \uc6cc\ud06c\ud50c\ub85c\uc6b0\uac00 \uc6d0\uc2dc HTML\uc744 \uac00\uc838\uc635\ub2c8\ub2e4(\uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8 \ubbf8\uc2e4\ud589 \ud06c\ub864\ub7ec\ub97c \uc2dc\ubbac\ub808\uc774\uc158).\n3.  \uc8fc\uc694 SEO \uae30\ub2a5(\ud14d\uc2a4\ud2b8 \ub0b4\uc6a9, \uc81c\ubaa9, \uba54\ud0c0 \ud0dc\uadf8 \ub4f1)\uc744 \ucd94\ucd9c\ud569\ub2c8\ub2e4.\n4.  LLM(OpenAI\ub97c \ud1b5\ud574)\uc774 \uc774\ub7ec\ud55c \uae30\ub2a5\uc744 \ubd84\uc11d\ud558\uc5ec \ub2e4\uc74c\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4:\n    - AI \uac00\ub3c5\uc131 \uc810\uc218(0-10)\n    - \uc0ac\uc774\ud2b8\uc758 AI \uce5c\ud654\uc131 \uc694\uc57d\n    - \uc2e4\ud589 \uac00\ub2a5\ud55c \ucd94\ucc9c \uc0ac\ud56d\n    - `robots.txt` \ud655\uc778 \ub9ac\ub9c8\uc778\ub354\n\n**\uc124\uc815 \uc694\uad6c \uc0ac\ud56d:**\n- **OpenAI \uacc4\uc815 \ubc0f API \ud0a4:** \"OpenAI Chat Model\" \ub178\ub4dc\uc5d0\uc11c \uc790\uaca9 \uc99d\uba85\uc744 \uad6c\uc131\ud569\ub2c8\ub2e4.\n- **n8n \uc778\uc2a4\ud134\uc2a4:** \uc774 \uc6cc\ud06c\ud50c\ub85c\uc6b0\ub294 \ud074\ub77c\uc6b0\ub4dc \ub610\ub294 \uc790\uccb4 \ud638\uc2a4\ud305\ub41c \ubaa8\ub4e0 n8n \uc778\uc2a4\ud134\uc2a4\uc5d0\uc11c \uc2e4\ud589\ub429\ub2c8\ub2e4.\n\n**\uc0ac\uc6a9 \ubc29\ubc95:**\n1.  \"OpenAI Chat Model\" \ub178\ub4dc\uac00 API \ud0a4\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud569\ub2c8\ub2e4.\n2.  \uc6cc\ud06c\ud50c\ub85c\uc6b0\ub97c \ud65c\uc131\ud654\ud569\ub2c8\ub2e4.\n3.  \"When chat message received\" \ud2b8\ub9ac\uac70\uac00 \uc81c\uacf5\ud558\ub294 \ucc44\ud305 URL\uc744 \uc5fd\ub2c8\ub2e4.\n\n**\ucee4\uc2a4\ud130\ub9c8\uc774\uc81c\uc774\uc158:**\n- **LLM \ubaa8\ub378:** \"OpenAI Chat Model\" \ub178\ub4dc\uc5d0\uc11c \ubaa8\ub378\uc744 \ubcc0\uacbd\ud569\ub2c8\ub2e4.\n- **\ubd84\uc11d \ud504\ub86c\ud504\ud2b8:** \"AI SEO Analysis\" \ub178\ub4dc\uc5d0\uc11c \ud504\ub86c\ud504\ud2b8\ub97c \uc218\uc815\ud569\ub2c8\ub2e4.\n\n\ud83d\udd17 *\uc124\uc815 \ubc0f \ucee4\uc2a4\ud130\ub9c8\uc774\uc81c\uc774\uc158\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \ub0b4\uc6a9\uc740 n8n.io\uc758 \ud15c\ud50c\ub9bf \uc124\uba85\uc744 \ucc38\uc870\ud558\uc138\uc694.*"
      },
      "typeVersion": 1
    },
    {
      "id": "a737c2cb-1d6c-4e69-9d92-c7177c42049a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        360,
        260
      ],
      "parameters": {
        "width": 540,
        "height": 460,
        "content": "# **\ud83d\ude80 Leonard van Hemert\uac00 \uac1c\ubc1c\ud588\uc2b5\ub2c8\ub2e4**  \n\n\uc774 **AI SEO \uac00\ub3c5\uc131 \uac10\uc0ac** \uc6cc\ud06c\ud50c\ub85c\uc6b0\ub97c \uc0ac\uc6a9\ud574 \uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4! \ud83c\udf89  \n\n\uc774 \uc6cc\ud06c\ud50c\ub85c\uc6b0\ub294 \uc0ac\uc6a9\uc790\uac00 AI \ub3c4\uad6c\uac00 \uc6f9\uc0ac\uc774\ud2b8\ub97c \uc5b4\ub5bb\uac8c '\ubcf4\ub294\uc9c0' \uc774\ud574\ud558\ub3c4\ub85d \ub3d5\uace0, AI \uce5c\ud654\uc131\uc744 \uac1c\uc120\ud558\uae30 \uc704\ud55c \uc2e4\ud589 \uac00\ub2a5\ud55c \ud1b5\ucc30\uc744 \uc81c\uacf5\ud558\uae30 \uc704\ud574 \ub9cc\ub4e4\uc5b4\uc84c\uc2b5\ub2c8\ub2e4.  \n\n\uc774\uac83\uc774 \uc720\uc6a9\ud558\ub2e4\uace0 \uc0dd\uac01\ub418\uba74, LinkedIn\uc5d0\uc11c \uc800\uc640 **\uc5f0\uacb0**\ud558\uc138\uc694. \uadf8\ub9ac\uace0 \uc81c \ucd5c\uc2e0 AI \ubc0f \uc790\ub3d9\ud654 \ud504\ub85c\uc81d\ud2b8\uc5d0 \ub300\ud55c \uc5c5\ub370\uc774\ud2b8\ub97c \ubc1b\uc73c\uc138\uc694!  \n\n\ud83d\udd17 **LinkedIn\uc5d0\uc11c \uc800\ub97c \ud314\ub85c\uc6b0\ud558\uc138\uc694**: [Leonard van Hemert](https://www.linkedin.com/in/leonard-van-hemert/)  \n\n\uc800\ub294 **n8n \ucee4\ubba4\ub2c8\ud2f0**\uc758 \uc9c0\uc6d0\uc5d0 \uc9c4\uc2ec\uc73c\ub85c \uac10\uc0ac\ub4dc\ub9ac\uba70, \uc5ec\ub7ec\ubd84\uc774 \uc774 \uc6cc\ud06c\ud50c\ub85c\uc6b0\ub97c \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud558\uace0 \uac1c\uc120\ud558\ub294\uc9c0 \uae30\ub2e4\ub9b4 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4! \ud83d\ude80  \n\n\ucd5c\uc801\ud654 \uc990\uac81\uac8c \ud558\uc138\uc694,  \n**Leonard van Hemert** \ud83d\udca1"
      },
      "typeVersion": 1
    },
    {
      "id": "7228e3be-1ef7-4f5a-bcb0-2a9299d53cfe",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        628,
        80
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "gpt-4o"
        },
        "options": {
          "temperature": 0.3
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    }
  ],
  "active": true,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "executionOrder": "v1",
    "executionTimeout": 300
  },
  "versionId": "9e18a350-a243-4368-b3d3-746a55bceb24",
  "connections": {
    "AI SEO Analysis": {
      "main": [
        []
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI SEO Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Sanitize Website URL": {
      "main": [
        [
          {
            "node": "Get HTML from Website",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract HTML Features": {
      "main": [
        [
          {
            "node": "AI SEO Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get HTML from Website": {
      "main": [
        [
          {
            "node": "Extract HTML Features",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "Sanitize Website URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}