{
  "nodes": [
    {
      "id": "45af47d2-0c42-4c57-a4e6-3885fab455b9",
      "name": "When Executed by Another Workflow",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -5072,
        656
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "Client ID"
            },
            {
              "name": "Blog S.NO."
            },
            {
              "name": "Blog Title"
            },
            {
              "name": "Content"
            },
            {
              "name": "OnPage SEO"
            },
            {
              "name": "Focus Keyword"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "78974e00-286b-4c3e-a4e5-2c1b13546032",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5792,
        368
      ],
      "parameters": {
        "width": 672,
        "height": 768,
        "content": "# Automated Blog Publishing to WordPress\n\nThis workflow (Part 2) receives written blog content from the Blog Creation workflow and handles complete WordPress publishing with AI-generated images, internal linking, SEO optimization, and automated client reporting.\n\n## How it works\n\nWhen triggered by blog writing automation, this workflow fetches project configuration to check if image creation is enabled. It then adds internal links to the content by analyzing existing keywords and target pages. If images are enabled, AI generates 3 custom images (1 thumbnail + 2 content images) using branded colors and prompts, uploads them to WordPress, and inserts them into the article. The complete blog is published with proper categories and featured image, then the tracking sheet is updated and clients are notified via Discord and the Reporting Manager workflow.\n\n## Setup steps\n\n1. **Add credentials**: Google Sheets OAuth, WordPress API tokens, OpenAI API, Discord bot, and Gemini API\n2. **Configure Project Sheet**: Add your master project sheet URL in \"Fetch Project Configuration\" with columns: Client ID, Website URL, Blog API, Image Creation, Image Instructions, Color/Font, Discord Channel ID, On Page Sheet\n3. **Set WordPress auth**: Update authorization tokens in all WordPress HTTP nodes with your API keys\n4. **Link Blog Writing Automation**: Ensure Blog Creation workflow triggers this workflow with correct workflow ID\n5. **Test end-to-end**: Run Part 1 manually and verify images generate, publish correctly, and reports send"
      },
      "typeVersion": 1
    },
    {
      "id": "2e6ae59e-5fef-4a86-8277-4f4cd774313c",
      "name": "Fetch Project Configuration",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -4816,
        656
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "=Sheet_ID"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "=Your_Sheet_URL"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "78701c90-927b-4e5c-a04b-2f9eb568bdc3",
      "name": "Prepare Client & Blog Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -4624,
        656
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c63dbe72-5506-4b32-bddc-180fcc71c5a6",
              "name": "Blog S No",
              "type": "string",
              "value": "={{ $('When Executed by Another Workflow').item.json['Blog S.NO.'] }}"
            },
            {
              "id": "11545e2e-6a51-4e90-affa-80010edeab15",
              "name": "Website URL",
              "type": "string",
              "value": "={{ $json['Website URL'] }}"
            },
            {
              "id": "cfaaf13f-4bad-4768-9614-c38976aa59ad",
              "name": "Blog Title",
              "type": "string",
              "value": "={{ $('When Executed by Another Workflow').item.json['Blog Title'] }}"
            },
            {
              "id": "b38e9177-27b8-4bc9-a4e5-e870adf3ff30",
              "name": "Content",
              "type": "string",
              "value": "={{ $('When Executed by Another Workflow').item.json.Content }}"
            },
            {
              "id": "d8e7d304-681d-446f-af17-f7fe356bb2ff",
              "name": "Auth Code",
              "type": "string",
              "value": "={{ $json['Blog API'] }}"
            },
            {
              "id": "190875f3-1afa-4d75-aebf-72457a830e88",
              "name": "OnPage SEO",
              "type": "string",
              "value": "={{ $('When Executed by Another Workflow').item.json['OnPage SEO'] }}"
            },
            {
              "id": "784d95a0-91e9-43b0-b181-e0352f35a325",
              "name": "Focus Keyword",
              "type": "string",
              "value": "={{ $('When Executed by Another Workflow').item.json['Focus Keyword'] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f7108bfc-278b-4e51-b4bd-14aadccf0c52",
      "name": "Fetch Internal Link Keywords",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        -4400,
        656
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "TGT Keywords"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Fetch Project Configuration').item.json['Project Information Sheet'] }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "fe08f46d-4ba0-433a-9eee-c3d8133f4fcc",
      "name": "Filter Valid URLs Only",
      "type": "n8n-nodes-base.filter",
      "position": [
        -4192,
        656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f1eeb525-d83c-45c8-87ff-8487b289dcc5",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json['Target Pages'] }}",
              "rightValue": "http"
            }
          ]
        }
      },
      "typeVersion": 2.2,
      "alwaysOutputData": true
    },
    {
      "id": "fe222653-d2a3-4954-b3a6-fda57902d85e",
      "name": "Combine All Keywords & URLs",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -3968,
        656
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "Keywords, Target Pages"
      },
      "typeVersion": 1
    },
    {
      "id": "161f2252-4f10-4f33-b0e7-f1f977d47b14",
      "name": "Add Internal Links to Content",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -3712,
        656
      ],
      "parameters": {
        "text": "=Focus Keyword: \n{{ $json.data.map(item => item.Keywords).join(', ') }}\nTargeted URLs: {{ $json.data.map(item => item[\"Target Pages\"]).join(', ') }}\nCategory: {{ $('Fetch Project Configuration').item.json.Categories }}\nContent: {{ $('When Executed by Another Workflow').item.json.Content }}\n",
        "options": {
          "systemMessage": "Role: You are an SEO expert\nTask: I have given the Focus Keyword and Targeted URLs so You need to check the unique keyword and find the opportunity in the content to anchor the page URL and Based on the Content Give the Category ID from the list of category I need only Number not text in category\n\nTask Description: do not modify the content just find the opportunity to add the links based on the keywords. Identify up to 3 natural internal linking opportunities.\n\nInstructions:\nDo not place anchors close to each other.\nDo not repeat the same anchor text\nDo not use anchor word from headings (h1\u2013h6) or FAQ questions.\nDo not rewrite, expand, or inject new content.\n\nHTML RULES:\n- Preserve the exact HTML structure, layout, and formatting.\n- Only add <a href=\"\"> tags where permitted.\n\nOUTPUT RULES:\n- Output ONLY the final HTML.\n- No explanations, comments, suggestions, or URL lists."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "ad181417-e352-404c-9632-1772bbf1bc16",
      "name": "Gemini AI Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -3712,
        864
      ],
      "parameters": {
        "options": {},
        "modelName": "=ai_model"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "38981104-28c3-41d1-a272-e1740b38adac",
      "name": "Parse Content & Category",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -3552,
        864
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\t\"content\": \"string\",\n\t\"category\": \"number\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "4908d8c9-764c-42bf-8d0b-74f545e85ed5",
      "name": "Check If Image Creation Enabled",
      "type": "n8n-nodes-base.if",
      "position": [
        -3280,
        656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "abb5d70a-2b61-4c2b-9c34-314da50aad52",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $node[\"Fetch Project Configuration\"].json['Image Creation'] }}",
              "rightValue": "Yes"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f84cdab8-fa27-4c4a-8d73-30e235f8cc03",
      "name": "Generate Image Prompts with AI",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -2688,
        464
      ],
      "parameters": {
        "text": "=**INPUT:**\nHeading: {{ $('Prepare Client & Blog Data').item.json['Blog Title'] }}\nContent: {{ $json.output.content }}\nImage Instructions: {{ $('Fetch Project Configuration').item.json['Image Instructions'] }}\nColor and Font family: {{ $('Fetch Project Configuration').item.json['Color and Font'] }}",
        "options": {
          "systemMessage": "=You are an AI agent specialized in creating image prompts and alt text for blog content. Your task is to analyze the given blog title and content, then generate appropriate image prompts with corresponding alt text.\n\n## YOUR TASK\n\nGenerate exactly **3 images**:\n1. **Thumbnail Image** - Main featured image for the blog\n2. **Content Image 1** - Supporting image for blog body content  \n3. **Content Image 2** - Supporting image for blog body content\n\n## IMAGE SPECIFICATIONS\n\n### Style Requirements\n\n- Realistic and natural \u2014 no artificial or cartoon-like images\n- Clean and professional appearance\n- Get the color from the Given Data\n\n### Thumbnail Image Requirements\n\n- Should represent the main topic of the blog\n- **SPECIAL DESIGN LAYOUT**: Main visual elements positioned in **upper portion** of image\n- **TEXT POSITIONING**: Bottom third features **transparent overlay banner** with headline text\n- **TEXT STYLE**: White text on transparent background positioned at **bottom of image**\n- Must have blog thumbnail look & feel - professional and clickable\n- Eye-catching and click-worthy design\n- Should work well as a featured image\n- **TEXT ALIGNMENT**: Ensure perfect text alignment and readability in bottom overlay\n\n### Content Images Requirements (Image 1 & 2)\n\n- Must be relevant to specific subtopics mentioned in the blog content\n- Should support and illustrate the written content\n- **STRICTLY NO TEXT** should appear anywhere in these images\n- **NO GRAPHICS WITH TEXT** - pure visual representation only\n- Focus on clean visual representation of concepts discussed\n- Images should be graphic/illustrative but completely text-free\n\n## CRITICAL TEXT INSTRUCTIONS\n\n### For Thumbnail Image:\n\n- **MANDATORY LAYOUT**: Visual elements in upper 2/3, text overlay in bottom 1/3\n- **TEXT OVERLAY**: Create semi-transparent dark overlay banner at bottom with small left-right margins, spanning nearly full width\n- **OVERLAY STYLE**: Semi-transparent (not fully transparent) to ensure text readability without completely hiding background elements\n- **NEVER** place text over main image elements (people, objects, focal points)\n- Main graphics and icons positioned in **upper portion** only\n- Keep text minimal and impactful in bottom overlay\n- Ensure high contrast between white text and semi-transparent dark overlay\n- **REALISTIC RENDERING**: Use realistic 3D rendering and smooth gradient effects\n\n### For Content Images (1 & 2):\n\n- **ABSOLUTELY NO TEXT** of any kind\n- **NO GRAPHICS WITH EMBEDDED TEXT**\n- **NO LOGOS OR TEXT ELEMENTS**\n- Pure visual content only\n- Focus on illustrative graphics and visual elements\n\n## STRICT AVOID LIST\n\n- Complex graphics with multiple competing elements\n- Long text paragraphs or excessive text\n- Cluttered or busy designs\n- Unrealistic or artificial-looking images\n- Dark or complicated backgrounds\n- **Text overlapping main image elements** (for thumbnails)\n- **Text positioned anywhere except bottom overlay** (for thumbnails)\n- **Any text in content images** (Images 1 & 2)\n\n## OUTPUT FORMAT\n\nFor each image, provide:\n- **Image Prompt**: Detailed description for image generation\n- **Alt Text**: SEO-friendly alternative text description\n\n## ANALYSIS APPROACH\n\n1. Read the blog title \u2014 understand the main topic\n2. Scan the blog content \u2014 identify key subtopics and themes\n3. Select relevant subtopics \u2014 choose 2 most important subtopics for content images\n4. Create thumbnail concept \u2014 design main featured image with upper visuals and bottom text overlay\n5. Generate realistic prompts \u2014 focus on natural, professional imagery\n6. Write descriptive short alt text \u2014 include relevant keywords for SEO\n\n## EXAMPLE PROMPT STRUCTURE\n\n**Thumbnail Image Prompt**: \"Professional blog thumbnail design with [subject] elements positioned in upper portion of image on clean (#fff9f6) background, [specific visual details in top area], bottom third features transparent overlay banner with white text headlines, realistic lighting, high quality, [theme colors if applicable], modern blog thumbnail layout, minimalist composition\"\n\n**Content Image Prompt**: \"Clean professional photograph of [subject] on (#fff9f6) background, [specific visual details], NO TEXT, realistic lighting, high quality, [theme colors if applicable], minimalist composition, graphic illustration style\"\n\n**Alt Text**: \"Descriptive text including relevant keywords from blog topic\"\n\n## CRITICAL FINAL INSTRUCTIONS\n\n### Text Management:\n\n- **Thumbnail**: White text in transparent bottom overlay ONLY - no text over main visuals\n- **Content Images**: ZERO text - purely visual graphics\n- Use minimal, relevant text in bottom banner according to blog title\n- Perfect text alignment in transparent overlay design\n\n### Visual Quality:\n\n- Blog thumbnail must follow upper visuals + bottom text overlay structure\n- Content images should be clean illustrative graphics\n- Maintain consistent professional look across all images\n- Focus on visual storytelling with proper layout separation\n- Avoice 3D illustration or pet animal illustrations do not add.\n- element should be real.\n\nNow analyze the provided blog title and content to generate **3 image prompts** with their corresponding alt text following these enhanced guidelines."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2
    },
    {
      "id": "050b31bb-9d76-4131-aca3-935285f6ffd0",
      "name": "OpenAI GPT Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -2688,
        752
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini",
          "cachedResultName": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "d015e9b2-d9ad-44af-acd1-eab95e8f34ea",
      "name": "Process Each Image",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -2000,
        464
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "421840df-673f-4878-bdaf-edb333cd50e1",
      "name": "Parse Image Prompts1",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -2624,
        656
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n\t\"Thumbnail Prompt\": \"\",\n    \"Alt Text Thumbnail Image\" : \"\",\n\t\"Image Prompt 1\": \"\",\n    \"Alt Text Image 1\" : \"\",\n    \"Image Prompt 2\" : \"\",\n    \"Alt Text Image 2\" : \"\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "f9864b48-8b7a-45dd-a6f5-a83978afec2e",
      "name": "Split into 3 Image Items",
      "type": "n8n-nodes-base.code",
      "position": [
        -2336,
        464
      ],
      "parameters": {
        "jsCode": "// N8N Function Node Code\n// Convert single output to 3 separate items for Thumbnail, Image 1, and Image 2\n\nconst inputData = $input.all()[0].json.output;\n\n// Create array of 3 items\nconst outputItems = [\n  {\n    json: {\n      imageType: \"thumbnail\",\n      imagePrompt: inputData[\"Thumbnail Prompt\"],\n      altText: inputData[\"Alt Text Thumbnail Image\"]\n    }\n  },\n  {\n    json: {\n      imageType: \"image1\", \n      imagePrompt: inputData[\"Image Prompt 1\"],\n      altText: inputData[\"Alt Text Image 1\"]\n    }\n  },\n  {\n    json: {\n      imageType: \"image2\",\n      imagePrompt: inputData[\"Image Prompt 2\"], \n      altText: inputData[\"Alt Text Image 2\"]\n    }\n  }\n];\n\nreturn outputItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "380d50ab-183e-47b1-80b4-c3f7262f34dd",
      "name": "Generate Image with DALL-E",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "onError": "continueErrorOutput",
      "position": [
        -1680,
        480
      ],
      "parameters": {
        "model": "gpt-image-1",
        "prompt": "={{ $json.imagePrompt }}",
        "options": {
          "size": "1536x1024"
        },
        "resource": "image"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "c2ffc4a8-e589-4aa4-a598-4763ebe195fb",
      "name": "Upload to WordPress Media",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        -1424,
        464
      ],
      "parameters": {
        "url": "={{ $node['Prepare Client & Blog Data'].json['Website URL'] }}wp-json/wp/v2/media",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "binaryData",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Disposition",
              "value": "=attachment; filename=\"{{ $node['Prepare Client & Blog Data'].json['Blog Title'].replace(/[^a-zA-Z0-9]+/g,'') }}\".png"
            },
            {
              "name": "Content-Type",
              "value": "image/png"
            },
            {
              "name": "Authorization",
              "value": "=Your_API"
            }
          ]
        },
        "inputDataFieldName": "data"
      },
      "typeVersion": 4.2
    },
    {
      "id": "d115c743-5906-4eb1-b006-d958e3995a97",
      "name": "Store Image Metadata",
      "type": "n8n-nodes-base.set",
      "position": [
        -1232,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8e41876a-7a5e-4e70-a29e-de148529cb41",
              "name": "id",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "4204dba4-cce1-4f23-96b4-00adbd0a3323",
              "name": "url",
              "type": "string",
              "value": "={{ $json.guid.raw }}"
            },
            {
              "id": "02723dd1-704e-42f7-a444-b1015cc98eae",
              "name": "type",
              "type": "string",
              "value": "={{ $('Process Each Image').item.json.imageType }}"
            },
            {
              "id": "477f85d2-7fec-48db-af28-c83ca2ca5432",
              "name": "alt",
              "type": "string",
              "value": "={{ $('Process Each Image').item.json.altText }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "1e821d49-d8ef-4ed3-b1b6-2ebf3f8038aa",
      "name": "Collect All Image Data",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1536,
        336
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "id"
            },
            {
              "fieldToAggregate": "url"
            },
            {
              "fieldToAggregate": "type"
            },
            {
              "fieldToAggregate": "alt"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "eeaa9871-65ca-45cd-8a4e-93a7a1da9485",
      "name": "Insert Images into Content",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -1072,
        336
      ],
      "parameters": {
        "text": "=**Blog title:** {{ $node['Prepare Client & Blog Data'].json['Blog Title'] }}\n\n**Blog Images DATA in JSON**\n{{ $json.url }}\n{{ $json.type }}\n{{ $json.alt }}\n\n**Current Existing Article:**\n{{ $('Add Internal Links to Content').item.json.output.content }}",
        "options": {
          "systemMessage": "=You are a content writer. I have a job for you.  \n\nBasically, I have created an article for my WordPress website also i have already uploaded the inner blog images i have their alt text and image url.\nAlso I will give you the blog title and some additional details that should be included in the article.  \n\nYour task is to add those additional details into the relevant place in the article **without changing anything else** also do not remove the <a href tag from the content. Simply merge the additional details into the article and return the complete updated article in **HTML format**. The input format should not be modified \u2014 keep it as it is.\n\nAlso add image 1 URL and image 2 URL in html image tag with alt text and first image means thumbnail image must be in top before article and you have to added those 2 images into relevant place in article.\n\n#crictial instruction\n- Do not remove the anchor text from the content\n- Use same URL of the image do not modify the URL\n- do not add intro or supporting text just return the article\n- do not add blog title in content.\n- FAQs section should be in last.\n- thumbnail image must be in top because article starts.\n- make sure to add image alt text which is provided.\n- 2nd image and 3rd should be placed in article where its make sense.\n- return complete updated article \n- before FAQs start add a headline \"FAQs\" if this is not available."
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "69a5acb4-b5ac-415f-861c-1f6dcb77472a",
      "name": "Gemini Content Assembly Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -1072,
        672
      ],
      "parameters": {
        "options": {},
        "modelName": "=ai_model"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3b633708-d238-4660-94e3-c0e7d1c05f15",
      "name": "Clean HTML Output",
      "type": "n8n-nodes-base.code",
      "position": [
        -560,
        336
      ],
      "parameters": {
        "jsCode": "// Get the raw JSON output from the first \"Generate Complete Blog\" node\nconst raw = $('Insert Images into Content').first().json.output;\n\n// Clean unwanted JS lines and code fences from the output\nconst cleaned = raw\n  .replace(/let cleaned = raw\\.replace\\(.*?\\);/gs, '') // remove unwanted JS line if present\n  .replace(/```(json|html)?/g, '') // remove code fences like ```json or ```html\n  .trim();\n\nreturn {\n  cleanedOutput: cleaned\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "9b6d47d3-37bd-4e13-b4c3-e238fc016fad",
      "name": "Publish Blog with Featured Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -352,
        336
      ],
      "parameters": {
        "url": "={{ $node['Prepare Client & Blog Data'].json['Website URL'] }}wp-json/wp/v2/posts",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "={{ $node['Prepare Client & Blog Data'].json['Blog Title'] }}"
            },
            {
              "name": "content",
              "value": "={{ $json.cleanedOutput }}"
            },
            {
              "name": "status",
              "value": "publish"
            },
            {
              "name": "categories",
              "value": "={{ $('Add Internal Links to Content').item.json.output.category }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=your_api_key"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c52c80e8-c106-432d-8fe7-a46b2d49944f",
      "name": "Set Thumbnail as Featured Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -80,
        336
      ],
      "parameters": {
        "url": "={{ $node['Prepare Client & Blog Data'].json['Website URL'] }}wp-json/wp/v2/posts/{{ $json.id }}",
        "method": "POST",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "featured_media",
              "value": "={{ $('Collect All Image Data').item.json.id[0] }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=your_api_key"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "721b01dd-fa8e-46fd-b5dc-5c979848b268",
      "name": "Publish Blog without Images",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        112,
        336
      ],
      "parameters": {
        "columns": {
          "value": {
            "row_number": "={{ $('When Executed by Another Workflow').item.json['Blog S.NO.'] }}",
            "Publish URLs": "={{ $json.guid.rendered }}",
            "Published Date": "={{ new Date($json.date).toISOString().split('T')[0] }}"
          },
          "schema": [
            {
              "id": "Focus Keyword",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Focus Keyword",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Content Topic",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Content Topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Brief URLs",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Brief URLs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Topic Approval",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Topic Approval",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Internal Linking URLs",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Internal Linking URLs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Words",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Words",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Content URLs",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Content URLs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Content Approval Approval ",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Content Approval Approval ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Publish URLs",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Publish URLs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Published Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Published Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Content Requirement & Posting"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $node['Fetch Project Configuration'].json['On Page Sheet'] }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "e9d7e687-57f3-492e-9a5e-0d8d97e7326c",
      "name": "Trigger Client Reporting Workflow",
      "type": "n8n-nodes-base.executeWorkflow",
      "onError": "continueRegularOutput",
      "position": [
        480,
        336
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "vL74JIN20ypJ559f",
          "cachedResultUrl": "/workflow/vL74JIN20ypJ559f",
          "cachedResultName": "Plan>Design>Test \u2014 Reporting Manager"
        },
        "workflowInputs": {
          "value": {
            "Post URL": "={{ $('Set Thumbnail as Featured Image').item.json.link }}",
            "Client ID": "={{ $('Fetch Project Configuration').item.json['Client ID'] }}",
            "Task Name": "Blog Publishing",
            "Task Brief": "=Publishing the Blog on the Website to target this keyword {{ $node[\"When Executed by Another Workflow\"].json['Focus Keyword'] }}, And this is the blog Topic: {{ $node[\"When Executed by Another Workflow\"].json['Blog Title'] }}",
            "Purpose of this Task": "To inform the client about the blog content.",
            "Benefits of this Task": "Helps target new keywords for improved Google search rankings. Increases visibility across LLM-powered search platforms. Supports overall SEO growth and organic traffic."
          },
          "schema": [
            {
              "id": "Client ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Client ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Task Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Task Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Task Brief",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Task Brief",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Post URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Post URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Purpose of this Task",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Purpose of this Task",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Benefits of this Task",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Benefits of this Task",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "0c1cc481-ac1f-4090-9e2d-2e10b02a77a9",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4816,
        512
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 192,
        "content": "## Data Preparation & Internal Linking\n\nReceives blog data from blog writing automation, fetches project settings, loads internal link keywords, filters valid URLs, and uses AI to add 3 natural anchor links to content with proper category assignment"
      },
      "typeVersion": 1
    },
    {
      "id": "e65486d6-256b-4350-a204-425dcfd56e48",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3280,
        336
      ],
      "parameters": {
        "color": 7,
        "width": 1840,
        "height": 384,
        "content": "## AI Image Generation Pipeline\n\nGenerates 3 branded images (thumbnail + 2 content images) using AI prompts, creates them with DALL-E, uploads to WordPress media library with alt text, and collects metadata for content insertion\n"
      },
      "typeVersion": 1
    },
    {
      "id": "73005934-a1d4-48bb-857c-f0754b8ccd91",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1072,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 1088,
        "height": 192,
        "content": "## Content Assembly & Publishing\n\nInserts generated images into content at strategic positions, cleans HTML output, publishes to WordPress with categories and featured image, then updates tracking sheets"
      },
      "typeVersion": 1
    },
    {
      "id": "99aee362-9501-4411-ac91-163c65c2f2a7",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        304,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 464,
        "height": 192,
        "content": "## Reporting & Notifications\n\nUpdates Google Sheets with live blog URL and publish date, sends Discord notification to project manager, and triggers Reporting Manager for client communication via email/Slack/WhatsApp"
      },
      "typeVersion": 1
    },
    {
      "id": "e15ba6b1-668d-4804-abbe-ff9ff0b02ce0",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2336,
        816
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 208,
        "content": "## Notifications\n\nSends Discord notification to project manager, and triggers Reporting Manager for client communication via email/Slack/WhatsApp"
      },
      "typeVersion": 1
    },
    {
      "id": "8b370369-0a88-4bb2-a741-5fe296622433",
      "name": "Publish Blog without Image",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        -2720,
        976
      ],
      "parameters": {
        "url": "={{ $node['Prepare Client & Blog Data'].json['Website URL'] }}wp-json/wp/v2/posts",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "={{ $node['Prepare Client & Blog Data'].json['Blog Title'] }}"
            },
            {
              "name": "content",
              "value": "={{ $json.output.content }}"
            },
            {
              "name": "status",
              "value": "publish"
            },
            {
              "name": "categories",
              "value": "={{ $json.output.category }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=your_api_key"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "750b4e1c-553d-4aa3-9cf2-c6eb80b91194",
      "name": "Update Sheet with Publish URL (No Images)",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -2464,
        976
      ],
      "parameters": {
        "columns": {
          "value": {
            "row_number": "={{ $node['Prepare Client & Blog Data'].json['Blog S No'] }}",
            "Publish URLs": "={{ $json.link }}",
            "Focus Keyword": "",
            "Published Date": "={{ $now.format('yyyy-MM-dd') }}"
          },
          "schema": [
            {
              "id": "Focus Keyword",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Focus Keyword",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Content Topic",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Content Topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Brief URLs",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Brief URLs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Topic Approval",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Topic Approval",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Internal Linking URLs",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Internal Linking URLs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Words",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Words",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Content URLs",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Content URLs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Content Approval Approval ",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Content Approval Approval ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Publish URLs",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Publish URLs",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Published Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Published Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Content Requirement & Posting"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $node['Prepare Client & Blog Data'].json['OnPage SEO'] }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "b2c19bda-d408-43dd-af8a-a52d21e8a821",
      "name": "Send Discord Notification",
      "type": "n8n-nodes-base.discord",
      "position": [
        -2272,
        976
      ],
      "parameters": {
        "content": "=<@{{ $node[\"Fetch Project Configuration\"].json['Project Manager Discord ID'] }}>\n\nA new article has just been published on the {{ $('Fetch Project Configuration').item.json['GMB Name'] }} Website.\n\nCheck it out here: \n{{ $json['Publish URLs'] }}\n\n\u2705 Please review the content and let us know if you\u2019d like any changes to the article publishing automation. ",
        "guildId": {
          "__rl": true,
          "mode": "list",
          "value": "835475793143529482",
          "cachedResultUrl": "https://discord.com/channels/835475793143529482",
          "cachedResultName": "Project Delivery"
        },
        "options": {},
        "resource": "message",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $node[\"Fetch Project Configuration\"].json['Discord Channel ID'] }}"
        }
      },
      "credentials": {
        "discordBotApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    }
  ],
  "connections": {
    "Gemini AI Model": {
      "ai_languageModel": [
        [
          {
            "node": "Add Internal Links to Content",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI GPT Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Image Prompts with AI",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Parse Image Prompts1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Clean HTML Output": {
      "main": [
        [
          {
            "node": "Publish Blog with Featured Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Each Image": {
      "main": [
        [
          {
            "node": "Collect All Image Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate Image with DALL-E",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Image Prompts1": {
      "ai_outputParser": [
        [
          {
            "node": "Generate Image Prompts with AI",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Store Image Metadata": {
      "main": [
        [
          {
            "node": "Process Each Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Collect All Image Data": {
      "main": [
        [
          {
            "node": "Insert Images into Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Valid URLs Only": {
      "main": [
        [
          {
            "node": "Combine All Keywords & URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Content & Category": {
      "ai_outputParser": [
        [
          {
            "node": "Add Internal Links to Content",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Split into 3 Image Items": {
      "main": [
        [
          {
            "node": "Process Each Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to WordPress Media": {
      "main": [
        [
          {
            "node": "Store Image Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Image with DALL-E": {
      "main": [
        [
          {
            "node": "Upload to WordPress Media",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert Images into Content": {
      "main": [
        [
          {
            "node": "Clean HTML Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Client & Blog Data": {
      "main": [
        [
          {
            "node": "Fetch Internal Link Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish Blog without Image": {
      "main": [
        [
          {
            "node": "Update Sheet with Publish URL (No Images)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine All Keywords & URLs": {
      "main": [
        [
          {
            "node": "Add Internal Links to Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Project Configuration": {
      "main": [
        [
          {
            "node": "Prepare Client & Blog Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Internal Link Keywords": {
      "main": [
        [
          {
            "node": "Filter Valid URLs Only",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add Internal Links to Content": {
      "main": [
        [
          {
            "node": "Check If Image Creation Enabled",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Content Assembly Model": {
      "ai_languageModel": [
        [
          {
            "node": "Insert Images into Content",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Generate Image Prompts with AI": {
      "main": [
        [
          {
            "node": "Split into 3 Image Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Image Creation Enabled": {
      "main": [
        [
          {
            "node": "Generate Image Prompts with AI",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Publish Blog without Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Thumbnail as Featured Image": {
      "main": [
        [
          {
            "node": "Publish Blog without Images",
            "type": "main",
            "index": 0
          },
          {
            "node": "Trigger Client Reporting Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish Blog with Featured Image": {
      "main": [
        [
          {
            "node": "Set Thumbnail as Featured Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Executed by Another Workflow": {
      "main": [
        [
          {
            "node": "Fetch Project Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Sheet with Publish URL (No Images)": {
      "main": [
        [
          {
            "node": "Send Discord Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}