{
    "meta": {
        "instanceId": "=",
        "templateCredsSetupCompleted": true
    },
    "nodes": [
        {
            "id": "bdc398f0-a882-4fbe-ac37-7ca7e15a1081",
            "name": "Sticky Note4",
            "type": "n8n-nodes-base.stickyNote",
            "position": [
                2080,
                -200
            ],
            "parameters": {
                "width": 460,
                "height": 340,
                "content": "![Tutorial](https:\/\/www.samirsaci.com\/content\/images\/2025\/04\/temp-8.png)\n[🎥 Check My Tutorial](https:\/\/www.youtube.com\/watch?v=LwTIro6Rapk)"
            },
            "typeVersion": 1
        },
        {
            "id": "d132a584-770e-438c-bd98-28a9c1afa780",
            "name": "When clicking ‘Test workflow’",
            "type": "n8n-nodes-base.manualTrigger",
            "position": [
                1000,
                120
            ],
            "parameters": [],
            "typeVersion": 1
        },
        {
            "id": "d51eec9d-a177-4f5e-89e5-c73b6109f5ce",
            "name": "Loop Over Items",
            "type": "n8n-nodes-base.splitInBatches",
            "position": [
                2100,
                640
            ],
            "parameters": {
                "options": []
            },
            "typeVersion": 3
        },
        {
            "id": "41da741b-1c1d-4d41-9a96-85cadacd1c8e",
            "name": "Sticky Note1",
            "type": "n8n-nodes-base.stickyNote",
            "position": [
                1000,
                -200
            ],
            "parameters": {
                "color": 7,
                "width": 1040,
                "height": 460,
                "content": "### 1. First Block: audit the page to extract all the images with their respective alternative text\nThis workflow sends an HTTP request to collect the HTML processed by the Javascript node to list all the images in the page with their alternative texts. The results are saved in a Google Sheet.\n\n#### How to setup?\n- **Set your page link** in the first node\n- **Record the results in a Google Sheet Node**:\n   1. Add your Google Sheet API credentials to access the Google Sheet file\n   2. Select the file using the list, an URL or an ID\n   3. Select the sheet in which you want to record your working sessions\n   4. Map the fields\n  [Learn more about the Google Sheet Node](https:\/\/docs.n8n.io\/integrations\/builtin\/app-nodes\/n8n-nodes-base.googlesheets)\n"
            },
            "typeVersion": 1
        },
        {
            "id": "e7a269cd-a2da-4ea9-9ec8-c023c45b9e96",
            "name": "Page Link",
            "type": "n8n-nodes-base.set",
            "position": [
                1200,
                120
            ],
            "parameters": {
                "options": [],
                "assignments": {
                    "assignments": [
                        {
                            "id": "e69e5e68-5cd1-4f81-a940-2e5202d5589b",
                            "name": "url",
                            "type": "string",
                            "value": "https:\/\/www.samirsaci.com\/sustainable-business-strategy-with-data-analytics\/"
                        },
                        {
                            "id": "8839ac43-5d6a-4656-b555-714f836fc687",
                            "name": "baseUrl",
                            "type": "string",
                            "value": "https:\/\/www.samirsaci.com"
                        }
                    ]
                }
            },
            "notesInFlow": true,
            "typeVersion": 3.4
        },
        {
            "id": "6e6b7801-1f4c-4d00-826d-184dff58cee1",
            "name": "Download Results",
            "type": "n8n-nodes-base.googleSheets",
            "position": [
                1440,
                640
            ],
            "parameters": {
                "options": [],
                "sheetName": {
                    "__rl": true,
                    "mode": "=",
                    "value": "gid=0",
                    "cachedResultUrl": "=",
                    "cachedResultName": "="
                },
                "documentId": {
                    "__rl": true,
                    "mode": "list",
                    "value": "=",
                    "cachedResultUrl": "=",
                    "cachedResultName": "="
                }
            },
            "typeVersion": 4.5
        },
        {
            "id": "1a137755-3f14-4881-93a5-db7f8678fa0d",
            "name": "altLength < 50",
            "type": "n8n-nodes-base.if",
            "position": [
                1660,
                640
            ],
            "parameters": {
                "options": [],
                "conditions": {
                    "options": {
                        "version": 2,
                        "leftValue": "",
                        "caseSensitive": true,
                        "typeValidation": "strict"
                    },
                    "combinator": "and",
                    "conditions": [
                        {
                            "id": "a3b0ca70-0496-4966-94fd-f2927ce02ba9",
                            "operator": {
                                "type": "number",
                                "operation": "lt"
                            },
                            "leftValue": "={{ $json.altLength }}",
                            "rightValue": 100
                        }
                    ]
                }
            },
            "typeVersion": 2.2
        },
        {
            "id": "60ea3935-313e-4d16-a8b8-a2fe7da8df82",
            "name": "Limit records",
            "type": "n8n-nodes-base.limit",
            "position": [
                1880,
                560
            ],
            "parameters": {
                "maxItems": 5
            },
            "typeVersion": 1
        },
        {
            "id": "5785deb6-1bf4-40a6-b556-42aad4c01c83",
            "name": "Generate altText",
            "type": "@n8n\/n8n-nodes-langchain.openAi",
            "position": [
                2320,
                560
            ],
            "parameters": {
                "text": "Please generate the alternative text (alt text) for this image under 150 characters.\t",
                "modelId": {
                    "__rl": true,
                    "mode": "list",
                    "value": "gpt-4o-2024-05-13",
                    "cachedResultName": "GPT-4O-2024-05-13"
                },
                "options": {
                    "maxTokens": 150
                },
                "resource": "image",
                "imageUrls": "={{ $('altLength < 50').item.json.src }}",
                "operation": "analyze"
            },
            "notesInFlow": true,
            "typeVersion": 1.8
        },
        {
            "id": "86051a7f-e91a-4913-9c19-772673ff6306",
            "name": "Update Results",
            "type": "n8n-nodes-base.googleSheets",
            "position": [
                2540,
                640
            ],
            "parameters": {
                "columns": {
                    "value": {
                        "page": "=",
                        "index": "={{ $('Loop Over Items').item.json.index }}",
                        "newAlt": "={{ $json.content }}"
                    },
                    "schema": [
                        {
                            "id": "index",
                            "type": "string",
                            "display": true,
                            "removed": false,
                            "required": false,
                            "displayName": "index",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "page",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "page",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "src",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "src",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "alt",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "alt",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "altLength",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "altLength",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "newAlt",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "newAlt",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "row_number",
                            "type": "string",
                            "display": true,
                            "removed": true,
                            "readOnly": true,
                            "required": false,
                            "displayName": "row_number",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        }
                    ],
                    "mappingMode": "defineBelow",
                    "matchingColumns": [
                        "index"
                    ],
                    "attemptToConvertTypes": false,
                    "convertFieldsToString": false
                },
                "options": [],
                "operation": "update",
                "sheetName": {
                    "__rl": true,
                    "mode": "list",
                    "value": "gid=0",
                    "cachedResultUrl": "=",
                    "cachedResultName": "="
                },
                "documentId": {
                    "__rl": true,
                    "mode": "list",
                    "value": "=",
                    "cachedResultUrl": "=",
                    "cachedResultName": "="
                }
            },
            "typeVersion": 4.5
        },
        {
            "id": "b1ab97f7-a89e-40c8-ada3-22fcc6da2dcd",
            "name": "Sticky Note",
            "type": "n8n-nodes-base.stickyNote",
            "position": [
                1000,
                320
            ],
            "parameters": {
                "color": 7,
                "width": 1920,
                "height": 520,
                "content": "### 2. SecondBlock: generate alternative text for the image with altLength < 50\nThis workflow sends an HTTP request to collect the HTML processed by the Javascript node to list all the images in the page with their alternative texts. The results are saved in a Google Sheet.\n\n#### How to setup?\n- **Set your page link** in the first node\n- **Record the results in a Google Sheet Node**:\n   1. Add your Google Sheet API credentials to access the Google Sheet file\n   2. Select the file using the list, an URL or an ID\n   3. Select the sheet in which you want to record your working sessions\n   4. Map the fields\n  [Learn more about the Google Sheet Node](https:\/\/docs.n8n.io\/integrations\/builtin\/app-nodes\/n8n-nodes-base.googlesheets)\n"
            },
            "typeVersion": 1
        },
        {
            "id": "c1bf1dcf-6789-43dd-9f15-29895c30fd23",
            "name": "Store Results",
            "type": "n8n-nodes-base.googleSheets",
            "position": [
                1860,
                120
            ],
            "parameters": {
                "columns": {
                    "value": {
                        "alt": "={{ $json.alt }}",
                        "src": "={{ $json.src }}",
                        "page": "={{ $('Page Link').item.json.url }}",
                        "index": "={{ $json.index }}",
                        "altLength": "={{ $json.altLength }}"
                    },
                    "schema": [
                        {
                            "id": "index",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "index",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "page",
                            "type": "string",
                            "display": true,
                            "removed": false,
                            "required": false,
                            "displayName": "page",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "src",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "src",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "alt",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "alt",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "altLength",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "altLength",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        },
                        {
                            "id": "newAlt",
                            "type": "string",
                            "display": true,
                            "required": false,
                            "displayName": "newAlt",
                            "defaultMatch": false,
                            "canBeUsedToMatch": true
                        }
                    ],
                    "mappingMode": "defineBelow",
                    "matchingColumns": [],
                    "attemptToConvertTypes": false,
                    "convertFieldsToString": false
                },
                "options": [],
                "operation": "append",
                "sheetName": {
                    "__rl": true,
                    "mode": "list",
                    "value": "gid=0",
                    "cachedResultUrl": "=",
                    "cachedResultName": "="
                },
                "documentId": {
                    "__rl": true,
                    "mode": "list",
                    "value": "=",
                    "cachedResultUrl": "=",
                    "cachedResultName": "="
                }
            },
            "notesInFlow": true,
            "typeVersion": 4.5
        },
        {
            "id": "fe71094e-3a22-4cda-90ad-4174258a9086",
            "name": "Download HTML",
            "type": "n8n-nodes-base.httpRequest",
            "position": [
                1420,
                120
            ],
            "parameters": {
                "url": "={{ $json.url }}",
                "options": []
            },
            "typeVersion": 4.2
        },
        {
            "id": "405fe4cf-5271-465c-8e2a-1f5d024228b6",
            "name": "Get Images urls with altText",
            "type": "n8n-nodes-base.code",
            "position": [
                1640,
                120
            ],
            "parameters": {
                "jsCode": "const html = $input.first().json.data;\nconst baseUrl = $('Page Link').first().json.baseUrl;\n\nconst imgTagRegex = \/<img\\b[^>]*>\/gi;\nconst altAttrRegex = \/alt\\s*=\\s*[\"']([^\"']*)[\"']\/i;\nconst srcAttrRegex = \/src\\s*=\\s*[\"']([^\"']*)[\"']\/i;\n\nconst imageTags = html.match(imgTagRegex) || [];\n\nconst results = imageTags.map((tag, index) => {\n  const altMatch = tag.match(altAttrRegex);\n  const srcMatch = tag.match(srcAttrRegex);\n\n  let alt = altMatch ? altMatch[1] : '[No alt text]';\n  let src = srcMatch ? srcMatch[1] : '[No src]';\n\n  \/\/ If src is relative, manually join with baseUrl\n  if (src !== '[No src]' && !src.startsWith('http')) {\n    if (baseUrl.endsWith('\/') && src.startsWith('\/')) {\n      src = baseUrl + src.slice(1);\n    } else if (!baseUrl.endsWith('\/') && !src.startsWith('\/')) {\n      src = baseUrl + '\/' + src;\n    } else {\n      src = baseUrl + src;\n    }\n  }\n\n  return {\n    index: index + 1,\n    src,\n    alt,\n    altLength: alt.length,\n  };\n});\n\nreturn results.map(item => ({ json: item }));"
            },
            "typeVersion": 2
        }
    ],
    "pinData": [],
    "connections": {
        "Page Link": {
            "main": [
                [
                    {
                        "node": "Download HTML",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Download HTML": {
            "main": [
                [
                    {
                        "node": "Get Images urls with altText",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Limit records": {
            "main": [
                [
                    {
                        "node": "Loop Over Items",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Update Results": {
            "main": [
                [
                    {
                        "node": "Loop Over Items",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "altLength < 50": {
            "main": [
                [
                    {
                        "node": "Limit records",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Loop Over Items": {
            "main": [
                [],
                [
                    {
                        "node": "Generate altText",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Download Results": {
            "main": [
                [
                    {
                        "node": "altLength < 50",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Generate altText": {
            "main": [
                [
                    {
                        "node": "Update Results",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "Get Images urls with altText": {
            "main": [
                [
                    {
                        "node": "Store Results",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        },
        "When clicking ‘Test workflow’": {
            "main": [
                [
                    {
                        "node": "Page Link",
                        "type": "main",
                        "index": 0
                    },
                    {
                        "node": "Download Results",
                        "type": "main",
                        "index": 0
                    }
                ]
            ]
        }
    }
}