AutomationFlowsAI & RAG › AI Ad Generation Pipeline

AI Ad Generation Pipeline

AI Ad Generation Pipeline. Uses airtable, agent, lmChatOpenAi, outputParserStructured. Scheduled trigger; 15 nodes.

Cron / scheduled trigger★★★★☆ complexityAI-powered15 nodesAirtableAgentOpenAI ChatOutput Parser StructuredOpenAIHTTP RequestGmail
AI & RAG Trigger: Cron / scheduled Nodes: 15 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → Airtable recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "AI Ad Generation Pipeline",
  "nodes": [
    {
      "id": "dd5f24cc-2488-4d20-8cbd-b670cc3af5c8",
      "name": "Every Minute",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        0,
        752
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 1
            }
          ]
        }
      }
    },
    {
      "id": "aa5e3b67-5586-48e6-bcfd-1eb3f1538deb",
      "name": "Find New Briefs",
      "type": "n8n-nodes-base.airtable",
      "typeVersion": 2.2,
      "position": [
        224,
        752
      ],
      "parameters": {
        "authentication": "airtableTokenApi",
        "resource": "record",
        "operation": "search",
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_AIRTABLE_BASE_ID",
          "cachedResultName": "GlowKit Ad Briefs"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_AIRTABLE_TABLE_ID",
          "cachedResultName": "Ad Briefs"
        },
        "filterByFormula": "{Status}=\"New\"",
        "returnAll": true,
        "options": {}
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "1f4a3dff-e6e9-402a-8340-b72c9d704de5",
      "name": "Mark Processing",
      "type": "n8n-nodes-base.airtable",
      "typeVersion": 2.2,
      "position": [
        448,
        752
      ],
      "parameters": {
        "authentication": "airtableTokenApi",
        "resource": "record",
        "operation": "update",
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_AIRTABLE_BASE_ID",
          "cachedResultName": "GlowKit Ad Briefs"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_AIRTABLE_TABLE_ID",
          "cachedResultName": "Ad Briefs"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "value": {
            "id": "={{ $json.id }}",
            "Status": "Processing"
          }
        },
        "options": {}
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "b607951a-7fe5-414c-a747-9066792de812",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        672,
        752
      ],
      "parameters": {
        "batchSize": 1
      }
    },
    {
      "id": "bb20ebb7-46d1-4b37-bd8b-d628d8436a19",
      "name": "Generate Ad Copy",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        896,
        240
      ],
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.fields.Brief }}",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "You are the in-house copywriter for GlowKit, a direct-to-consumer skincare brand that sells on Meta Ads (Instagram/Facebook).\n\nBrand voice: Friendly, confident, science-backed but not clinical. Short, punchy sentences. Never use hype words like \"miracle\", \"magic\", or \"revolutionary\".\n\nAudience: Women 25-40, skincare-curious, shop on Instagram.\n\nProduct context: Vitamin C serum, hydrating cleanser, and bundle deals.\n\nGiven a one-line ad brief, produce:\n- Exactly 3 short scroll-stopping hooks (each a single strong opening line/headline for the ad's hook).\n- One Meta primary text (roughly 125 words or fewer) in the GlowKit voice that expands on the best hook.\n- One headline of 40 characters or fewer.\n- One clear call-to-action (e.g. \"Shop Now\", \"Get 20% Off\").\n- One detailed image_prompt for an AI image generator: product-focused, natural light, Instagram-feed aesthetic, no text or typography rendered in the image itself.\n\nBase everything on the brief you are given. Do not invent claims that aren't implied by the brief."
        }
      },
      "onError": "continueErrorOutput"
    },
    {
      "id": "8f17e5d9-f9b1-4ebb-91fe-39df0cb88344",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        912,
        464
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5-mini",
          "cachedResultName": "gpt-5-mini"
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "2cb4a8c8-c4d1-4fb0-b5a1-1266a1a1e1fd",
      "name": "Ad Copy Schema",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        1040,
        464
      ],
      "parameters": {
        "schemaType": "fromJson",
        "jsonSchemaExample": "{\"hooks\":[\"Hook one text\",\"Hook two text\",\"Hook three text\"],\"primary_text\":\"Primary ad text in GlowKit's voice, about 125 words or fewer.\",\"headline\":\"Short headline, 40 chars or fewer\",\"cta\":\"Shop Now\",\"image_prompt\":\"Detailed, product-focused, Instagram-style image prompt with no text in the image.\"}"
      }
    },
    {
      "id": "c3ceb2c5-e567-4782-ab4a-018bf875c5b3",
      "name": "Parse & Validate Ad Copy",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1248,
        176
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "language": "javaScript",
        "jsCode": "const raw = $input.item.json.output ?? $input.item.json;\nconst hooks = raw.hooks;\nconst primaryText = raw.primary_text;\nconst headline = raw.headline;\nconst cta = raw.cta;\nconst imagePrompt = raw.image_prompt;\n\nif (!Array.isArray(hooks) || hooks.length !== 3 || hooks.some((h) => typeof h !== 'string' || !h.trim())) {\n  throw new Error('Invalid ad copy: expected exactly 3 non-empty hooks, got ' + JSON.stringify(hooks));\n}\nif (typeof headline !== 'string' || !headline.trim() || headline.length > 40) {\n  throw new Error('Invalid ad copy: headline must be a non-empty string of 40 characters or fewer, got \"' + headline + '\"');\n}\nif (typeof primaryText !== 'string' || !primaryText.trim()) {\n  throw new Error('Invalid ad copy: primary_text is missing or empty');\n}\nconst wordCount = primaryText.trim().split(/\\s+/).length;\nif (wordCount > 150) {\n  throw new Error('Invalid ad copy: primary_text is too long (' + wordCount + ' words, max ~125)');\n}\nif (typeof cta !== 'string' || !cta.trim()) {\n  throw new Error('Invalid ad copy: cta is missing or empty');\n}\nif (typeof imagePrompt !== 'string' || !imagePrompt.trim()) {\n  throw new Error('Invalid ad copy: image_prompt is missing or empty');\n}\n\nreturn {\n  json: {\n    hook1: hooks[0],\n    hook2: hooks[1],\n    hook3: hooks[2],\n    primaryText: primaryText,\n    headline: headline,\n    cta: cta,\n    imagePrompt: imagePrompt\n  }\n};"
      },
      "onError": "continueErrorOutput"
    },
    {
      "id": "48e930ac-454f-4e29-ae0c-42e8f8bae0cf",
      "name": "Generate Ad Image",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 2.3,
      "position": [
        1472,
        144
      ],
      "parameters": {
        "resource": "image",
        "operation": "generate",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-image-1-mini",
          "cachedResultName": "gpt-image-1-mini"
        },
        "prompt": "={{ $json.imagePrompt }}",
        "options": {
          "size": "1024x1024",
          "quality": "medium",
          "binaryPropertyOutput": "data"
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput"
    },
    {
      "id": "1444c1aa-40e4-4c0b-a4b2-451ac1336907",
      "name": "Prepare Image Upload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1696,
        144
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "language": "javaScript",
        "jsCode": "const bin = $input.item.binary && $input.item.binary.data;\nif (!bin || !bin.data) {\n  throw new Error('OpenAI image generation did not return binary image data');\n}\nreturn {\n  json: {\n    imageBase64: bin.data,\n    mimeType: bin.mimeType || 'image/png',\n    fileName: bin.fileName || 'glowkit-ad-image.png'\n  }\n};"
      },
      "onError": "continueErrorOutput"
    },
    {
      "id": "eb643300-1a2d-489b-9545-2dfe364dd147",
      "name": "Upload Image to Airtable",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1920,
        80
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://content.airtable.com/v0/YOUR_AIRTABLE_BASE_ID/{{ $('Loop Over Items').item.json.id }}/fld2oFdcjRI4HsG7o/uploadAttachment",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "airtableTokenApi",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ { \"contentType\": $json.mimeType, \"file\": $json.imageBase64, \"filename\": $json.fileName } }}",
        "options": {}
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput"
    },
    {
      "id": "b47b3dce-0cfd-4368-af22-0875df1f1a68",
      "name": "Write Ad Creative",
      "type": "n8n-nodes-base.airtable",
      "typeVersion": 2.2,
      "position": [
        2144,
        0
      ],
      "parameters": {
        "authentication": "airtableTokenApi",
        "resource": "record",
        "operation": "update",
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_AIRTABLE_BASE_ID",
          "cachedResultName": "GlowKit Ad Briefs"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_AIRTABLE_TABLE_ID",
          "cachedResultName": "Ad Briefs"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "value": {
            "id": "={{ $('Loop Over Items').item.json.id }}",
            "Hook 1": "={{ $('Parse & Validate Ad Copy').item.json.hook1 }}",
            "Hook 2": "={{ $('Parse & Validate Ad Copy').item.json.hook2 }}",
            "Hook 3": "={{ $('Parse & Validate Ad Copy').item.json.hook3 }}",
            "Primary Text": "={{ $('Parse & Validate Ad Copy').item.json.primaryText }}",
            "Headline": "={{ $('Parse & Validate Ad Copy').item.json.headline }}",
            "CTA": "={{ $('Parse & Validate Ad Copy').item.json.cta }}",
            "Status": "Ready for Review"
          }
        },
        "options": {}
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput"
    },
    {
      "id": "d41af511-9083-4c2b-a31c-bf84c3166ed8",
      "name": "Notify Ready",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.2,
      "position": [
        2368,
        144
      ],
      "parameters": {
        "resource": "message",
        "operation": "send",
        "sendTo": "you@yourcompany.com",
        "subject": "=\u2705 New ad variants ready for GlowKit \u2014 {{ $('Loop Over Items').item.json.fields.Brief.slice(0, 60) }}",
        "emailType": "text",
        "message": "=New GlowKit ad creative is ready for review.\n\nBrief: {{ $(\"Loop Over Items\").item.json.fields.Brief }}\n\nHeadline: {{ $(\"Parse & Validate Ad Copy\").item.json.headline }}\nCTA: {{ $(\"Parse & Validate Ad Copy\").item.json.cta }}\n\nOpen the GlowKit Ad Briefs base in Airtable to review and approve.",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "ff536191-8a48-422d-81fd-c4d102330613",
      "name": "Mark Error",
      "type": "n8n-nodes-base.airtable",
      "typeVersion": 2.2,
      "position": [
        2368,
        384
      ],
      "parameters": {
        "authentication": "airtableTokenApi",
        "resource": "record",
        "operation": "update",
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_AIRTABLE_BASE_ID",
          "cachedResultName": "GlowKit Ad Briefs"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_AIRTABLE_TABLE_ID",
          "cachedResultName": "Ad Briefs"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "value": {
            "id": "={{ $('Loop Over Items').item.json.id }}",
            "Status": "Error",
            "Notes": "={{ $json.error?.message ?? $json.message ?? \"Unknown error during ad generation\" }}"
          }
        },
        "options": {}
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "4a05561b-319e-4227-bf0f-218e25478eb9",
      "name": "Notify Failure",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.2,
      "position": [
        2592,
        672
      ],
      "parameters": {
        "resource": "message",
        "operation": "send",
        "sendTo": "you@yourcompany.com",
        "subject": "=\u26a0\ufe0f Ad generation failed for GlowKit \u2014 {{ $('Loop Over Items').item.json.fields.Brief.slice(0, 60) }}",
        "emailType": "text",
        "message": "=Ad generation failed for a GlowKit brief and the record was marked Error.\n\nBrief: {{ $(\"Loop Over Items\").item.json.fields.Brief }}\nError: {{ $(\"Mark Error\").item.json.fields.Notes }}\n\nOpen the GlowKit Ad Briefs base in Airtable to review the Notes field.",
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    }
  ],
  "connections": {
    "Every Minute": {
      "main": [
        [
          {
            "node": "Find New Briefs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find New Briefs": {
      "main": [
        [
          {
            "node": "Mark Processing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Processing": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Generate Ad Copy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Ad Copy": {
      "main": [
        [
          {
            "node": "Parse & Validate Ad Copy",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Ad Copy",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Ad Copy Schema": {
      "ai_outputParser": [
        [
          {
            "node": "Generate Ad Copy",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Parse & Validate Ad Copy": {
      "main": [
        [
          {
            "node": "Generate Ad Image",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Ad Image": {
      "main": [
        [
          {
            "node": "Prepare Image Upload",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Image Upload": {
      "main": [
        [
          {
            "node": "Upload Image to Airtable",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Image to Airtable": {
      "main": [
        [
          {
            "node": "Write Ad Creative",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Ad Creative": {
      "main": [
        [
          {
            "node": "Notify Ready",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Ready": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Error": {
      "main": [
        [
          {
            "node": "Notify Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Failure": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

AI Ad Generation Pipeline. Uses airtable, agent, lmChatOpenAi, outputParserStructured. Scheduled trigger; 15 nodes.

Source: https://github.com/errolagatep/ai-ad-generation-pipeline/blob/main/workflow.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

This n8n automation workflow automates the creation, scripting, production, and posting of YouTube videos. It leverages AI (OpenAI), image generation (PIAPI), video rendering (Shotstack), and platform

Agent, OpenAI Chat, Airtable Tool +7
AI & RAG

Schedules automated vendor pricing analysis across multiple sources. Fetches delivery reliability and contract data, analyzes vendor performance using Claude AI, then distributes consolidated reports

HTTP Request, Airtable, OpenAI Chat +9
AI & RAG

This powerful automation turns LinkedIn influencer activity into high performing Amazon seller content, fully hands-off. It runs in two phases: AI Content Generator Retrieves influencer usernames from

Agent, OpenAI Chat, Output Parser Structured +5
AI & RAG

This workflow automates tenant screening by analyzing payment history, credit, and employment data to predict rental risks. Designed for property managers, landlords, and real estate agencies, it solv

HTTP Request, Agent, OpenAI Chat +6
AI & RAG

Complete PostgreSQL-backed system: Keyword scoring → AI research → Multi-part content generation → fal.ai Nano Banana image generation → WordPress publishing

WordPress, OpenAI, Perplexity +8