Generar automáticamente anuncios de Google con Claude 3.5, Channable y Relevance AI

Avanzado

Este es unContent Creation, Multimodal AIflujo de automatización del dominio deautomatización que contiene 19 nodos.Utiliza principalmente nodos como If, Set, Code, Slack, Aggregate. Generar automáticamente anuncios de Google con Claude 3.5, Channable y Relevance AI

Requisitos previos
  • Bot Token de Slack o URL de Webhook
  • Pueden requerirse credenciales de autenticación para la API de destino
  • Credenciales de API de Google Sheets
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "meta": {
    "instanceId": "04fd795d32aabb18b913b4a3350b5cd0e9313a422ea0e7bdac0da2fb76cac9f7"
  },
  "nodes": [
    {
      "id": "b07b40c1-4c8c-4c35-aa07-be7025ed68b2",
      "name": "Obtener Feed de Productos",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "CORRECTED: Uses v1 API if available, or replace with your e-commerce platform feed endpoint",
      "position": [
        -1380,
        820
      ],
      "parameters": {
        "url": "={{$env.CHANNABLE_API_URL}}/v1/projects/{{$env.PROJECT_ID}}/items",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "luTyM3gZSgwhM8i0",
          "name": "Header Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4b90a3bc-da44-44bc-b19a-d81427545f26",
      "name": "Formatear para CSV",
      "type": "n8n-nodes-base.set",
      "notes": "Formats compliant ads into CSV structure",
      "position": [
        560,
        700
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3.3
    },
    {
      "id": "bea6c2f0-4a95-4848-85a1-780cc048b26d",
      "name": "Alerta - No Conforme",
      "type": "n8n-nodes-base.slack",
      "notes": "Sends Slack alert for non-compliant ads. Can replace with Email node.",
      "position": [
        560,
        900
      ],
      "webhookId": "50d6fb83-2c83-4b57-80f9-5bb46d6b9fdf",
      "parameters": {
        "text": "=⚠️ Non-Compliant Ad Flagged\n\n*Product ID:* {{$json.product_id}}\n*Product Title:* {{$json.product_title}}\n*Category:* {{$json.category}}\n\n*Generated Headline:* {{$json.validated_headline}}\n*Generated Description:* {{$json.validated_description}}\n\n*Compliance Issues:* Check agent output\n\n*Timestamp:* {{$json.validation_timestamp}}",
        "otherOptions": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "95f53395-e93d-4309-8f98-d2b2378cbb13",
      "name": "Agregar Lotes",
      "type": "n8n-nodes-base.aggregate",
      "notes": "Combines all processed batches into single dataset",
      "position": [
        760,
        700
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "56492a38-1188-4b35-999f-14017ac76484",
      "name": "Guardar en Hojas Google",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "CORRECTED: Saves CSV data to Google Sheets instead of Channable API upload (which doesn't exist). You can then: 1) Import manually to Google Ads, 2) Use Channable scheduled import, or 3) Build Google Ads API direct upload",
      "position": [
        1160,
        700
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Generated Ads"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{$env.GOOGLE_SHEET_ID}}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "0xHwEMloLvs9YH5S",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "f25d680c-28ad-43f5-96c8-0f022cf1a710",
      "name": "Activador Programado - Diario1",
      "type": "n8n-nodes-base.scheduleTrigger",
      "notes": "Triggers workflow daily at midnight. Can also be triggered manually.",
      "position": [
        -1600,
        820
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 0 * * *"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "01a193ae-a04f-4a04-9c3e-0a40c8e197c5",
      "name": "Dividir en Lotes1",
      "type": "n8n-nodes-base.splitInBatches",
      "notes": "Processes 50 products at a time to avoid API rate limits",
      "position": [
        -1140,
        820
      ],
      "parameters": {
        "options": {},
        "batchSize": 50
      },
      "typeVersion": 3
    },
    {
      "id": "50792985-2a29-4aeb-8191-2a1ef3d7ec97",
      "name": "Generar Texto Publicitario - Relevance AI1",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "CORRECTED: Uses /trigger endpoint with tool ID from environment variable. Get your actual tool ID after creating in Relevance AI.",
      "position": [
        -880,
        800
      ],
      "parameters": {
        "url": "={{$env.RELEVANCE_AI_API_URL}}/tools/google_text_ad_copy_generator/run",
        "method": "POST",
        "options": {
          "timeout": 60000
        },
        "jsonBody": "={\n  \"params\": {\n    \"product_title\": \"{{$json.title}}\",\n    \"product_description\": \"{{$json.description}}\",\n    \"price\": \"{{$json.price}}\",\n    \"category\": \"{{$json.category}}\",\n    \"brand\": \"{{$json.brand}}\"\n  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "luTyM3gZSgwhM8i0",
          "name": "Header Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "17d67f83-8300-41c5-a3ac-9b7ea4bc25c2",
      "name": "Validar Límites de Caracteres1",
      "type": "n8n-nodes-base.code",
      "notes": "Validates headline ≤30 chars and description ≤90 chars. This is the fix from the YouTube video for accurate character counting.",
      "position": [
        -560,
        800
      ],
      "parameters": {
        "jsCode": "// Character limit validation with accurate counting\n\nconst headline = $input.item.json.headline || '';\nconst description = $input.item.json.description || '';\n\n// Function to accurately count displayed characters\nfunction getCharacterCount(str) {\n  str = str.trim();\n  return str.length;\n}\n\n// Validate headline (max 30 characters)\nlet headlineResult = {};\nconst headlineCount = getCharacterCount(headline);\n\nif (headlineCount > 30) {\n  let truncated = headline.substring(0, 27).trim();\n  truncated = truncated.replace(/[,.\\-:]$/, '');\n  headlineResult = {\n    headline: truncated + '...',\n    char_count: truncated.length + 3,\n    truncated: true,\n    original: headline\n  };\n} else {\n  headlineResult = {\n    headline: headline,\n    char_count: headlineCount,\n    truncated: false,\n    original: headline\n  };\n}\n\n// Validate description (max 90 characters)\nlet descriptionResult = {};\nconst descriptionCount = getCharacterCount(description);\n\nif (descriptionCount > 90) {\n  let truncated = description.substring(0, 87).trim();\n  truncated = truncated.replace(/[,.\\-:]$/, '');\n  descriptionResult = {\n    description: truncated + '...',\n    char_count: truncated.length + 3,\n    truncated: true,\n    original: description\n  };\n} else {\n  descriptionResult = {\n    description: description,\n    char_count: descriptionCount,\n    truncated: false,\n    original: description\n  };\n}\n\n// Return validated data with original product info\nreturn {\n  product_id: $input.item.json.product_id || $input.item.json.id,\n  product_title: $input.item.json.product_title || $input.item.json.title,\n  validated_headline: headlineResult.headline,\n  headline_char_count: headlineResult.char_count,\n  headline_truncated: headlineResult.truncated,\n  validated_description: descriptionResult.description,\n  description_char_count: descriptionResult.char_count,\n  description_truncated: descriptionResult.truncated,\n  category: $input.item.json.category,\n  final_url: $input.item.json.product_url || $input.item.json.link,\n  validation_timestamp: new Date().toISOString()\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "534ea658-ea94-4d4c-a4e3-5d5fa1c699b6",
      "name": "Agente de Verificación de Cumplimiento1",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "CORRECTED: Uses /agents/trigger with agent_id in body. Get your actual agent ID from Relevance AI.",
      "position": [
        -160,
        800
      ],
      "parameters": {
        "url": "={{$env.RELEVANCE_AI_API_URL}}/agents/google_ads_compliance_checker/run",
        "method": "POST",
        "options": {
          "timeout": 60000
        },
        "jsonBody": "={\n  \"message\": {\n    \"role\": \"user\",\n    \"content\": \"Check compliance for this ad: Headline: {{$json.validated_headline}}, Description: {{$json.validated_description}}, Category: {{$json.category}}\"\n  },\n  \"agent_id\": \"{{$env.RELEVANCE_AGENT_COMPLIANCE_ID}}\"\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "luTyM3gZSgwhM8i0",
          "name": "Header Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c9bfe847-7215-4ae5-a61e-4eb24ae1da0c",
      "name": "SI Conforme1",
      "type": "n8n-nodes-base.if",
      "notes": "Routes ads based on compliance status. APPROVED ads go to formatting, others trigger alert.",
      "position": [
        160,
        800
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "string": [
            {
              "value1": "={{$json.compliance_status || $json.output}}",
              "value2": "APPROVED",
              "operation": "contains"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "5a27e0f1-d4e7-4a81-9700-dd1c368fbb0b",
      "name": "Generar Archivo CSV1",
      "type": "n8n-nodes-base.code",
      "notes": "Converts JSON to properly escaped CSV format",
      "position": [
        960,
        700
      ],
      "parameters": {
        "jsCode": "// Generate CSV from aggregated data\n\nconst items = $input.all();\n\n// CSV headers\nconst headers = ['product_id', 'headline', 'description', 'final_url', 'display_url'];\n\n// Create CSV rows\nconst rows = items.map(item => {\n  const json = item.json;\n  return [\n    json.product_id || '',\n    json.headline || '',\n    json.description || '',\n    json.final_url || '',\n    json.display_url || ''\n  ];\n});\n\n// Convert to CSV string\nconst csvRows = [headers, ...rows];\nconst csvString = csvRows\n  .map(row => row.map(cell => `\"${String(cell).replace(/\"/g, '\"\"')}\"`).join(','))\n  .join('\\n');\n\n// Return CSV data\nreturn {\n  csv_data: csvString,\n  total_ads: rows.length,\n  generated_at: new Date().toISOString(),\n  filename: `google_ads_${new Date().toISOString().split('T')[0]}.csv`\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "55d4429b-b4a9-4a19-bb34-2f58d7881a5c",
      "name": "Notificación de Éxito1",
      "type": "n8n-nodes-base.slack",
      "notes": "Sends success notification with summary",
      "position": [
        1360,
        700
      ],
      "webhookId": "04afb760-a7e8-4d2d-9827-1ed01108405d",
      "parameters": {
        "text": "=✅ *Google Ads Generation Complete*\n\n📊 *Summary:*\n• Total Ads Generated: {{$node['Generate CSV File1'].json.total_ads}}\n• Saved to Google Sheets: {{$env.GOOGLE_SHEET_ID}}\n• Timestamp: {{$node['Generate CSV File1'].json.generated_at}}\n\n🎯 *Next Steps:*\n• Review ads in Google Sheet\n• Import to Google Ads (manual or scheduled)\n• Monitor for disapprovals in 24 hours\n\n💡 CSV filename: {{$node['Generate CSV File1'].json.filename}}",
        "otherOptions": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "9af47779-8ca3-4e7c-9d3d-76f419c45361",
      "name": "Nota Adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2060,
        760
      ],
      "parameters": {
        "width": 360,
        "height": 220,
        "content": "## 🟦 Schedule Trigger - Daily\n\n### 🕓 Purpose: Automatically runs every night at midnight (0 0 * * *).\nTip: You can also execute manually for testing.\n\n💡 Use to refresh and generate new ad copy daily."
      },
      "typeVersion": 1
    },
    {
      "id": "d563b4b9-7239-4bb1-ab62-73b924643715",
      "name": "Nota Adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1500,
        400
      ],
      "parameters": {
        "width": 340,
        "height": 320,
        "content": "## 🟦 Get Product Feed (Channable)\n### 📦 Purpose: Fetches live product data (title, price, brand, description, category).\nAPI: GET {{$env.CHANNABLE_API_URL}}/v1/projects/{{$env.PROJECT_ID}}/items\n\n#### ⚙️ Replace or connect to your store’s API if Channable isn’t used.\n✅ Returns all active products for ad generation."
      },
      "typeVersion": 1
    },
    {
      "id": "538ff6d6-5496-42db-90c4-2f22a1f228f4",
      "name": "Nota Adhesiva2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1240,
        980
      ],
      "parameters": {
        "width": 320,
        "height": 240,
        "content": "## 🟦 Split Into Batches\n\n### 🧮 Purpose: Processes up to 50 products per batch.\n\nPrevents hitting API rate limits from Relevance AI or Channable.\n⚡ Adjust batch size depending on product volume and plan limits."
      },
      "typeVersion": 1
    },
    {
      "id": "bb106886-79a8-437c-8f74-50939befe720",
      "name": "Nota Adhesiva4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1020,
        400
      ],
      "parameters": {
        "width": 340,
        "height": 320,
        "content": "## 🟦 Generate Ad Copy - Relevance AI\n### ✍️ Purpose: Calls your Relevance AI Tool to generate Google Ads headlines & descriptions.\nAPI: POST /tools/google_text_ad_copy_generator/run\n\nUses product title, description, price, brand, and category.\n🧠 Model: Claude 3.5 / GPT-4 via Relevance AI."
      },
      "typeVersion": 1
    },
    {
      "id": "eabe3ce0-d216-426d-8cc3-e1411f36c385",
      "name": "Nota Adhesiva3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -680,
        980
      ],
      "parameters": {
        "width": 320,
        "height": 300,
        "content": "## 🟦 Validate Character Limits\n\n🔍 Purpose: Ensures headlines ≤30 chars and descriptions ≤90 chars.\n\nUses JavaScript to count accurately and truncate gracefully.\n✨ Automatically cleans trailing punctuation and spaces.\n💡 Fixes the common issue where ads get disapproved for “too long” text."
      },
      "typeVersion": 1
    },
    {
      "id": "adb78971-8b7e-4eaf-9d9a-c47439b35c12",
      "name": "Nota Adhesiva5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        400
      ],
      "parameters": {
        "width": 340,
        "height": 320,
        "content": "## 🟦 Compliance Check Agent\n\n🧠 Purpose: Checks generated ad text for Google Ads policy compliance.\nAPI: POST /agents/google_ads_compliance_checker/run\n\nFlags emojis, exaggerated claims, restricted terms, etc.\nReturns \"APPROVED\" or \"REJECTED\".\n🔐 Uses your Relevance AI Agent ID."
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "c9bfe847-7215-4ae5-a61e-4eb24ae1da0c": {
      "main": [
        [
          {
            "node": "4b90a3bc-da44-44bc-b19a-d81427545f26",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "bea6c2f0-4a95-4848-85a1-780cc048b26d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4b90a3bc-da44-44bc-b19a-d81427545f26": {
      "main": [
        [
          {
            "node": "95f53395-e93d-4309-8f98-d2b2378cbb13",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b07b40c1-4c8c-4c35-aa07-be7025ed68b2": {
      "main": [
        [
          {
            "node": "01a193ae-a04f-4a04-9c3e-0a40c8e197c5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "95f53395-e93d-4309-8f98-d2b2378cbb13": {
      "main": [
        [
          {
            "node": "5a27e0f1-d4e7-4a81-9700-dd1c368fbb0b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5a27e0f1-d4e7-4a81-9700-dd1c368fbb0b": {
      "main": [
        [
          {
            "node": "56492a38-1188-4b35-999f-14017ac76484",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "01a193ae-a04f-4a04-9c3e-0a40c8e197c5": {
      "main": [
        [
          {
            "node": "50792985-2a29-4aeb-8191-2a1ef3d7ec97",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "56492a38-1188-4b35-999f-14017ac76484": {
      "main": [
        [
          {
            "node": "55d4429b-b4a9-4a19-bb34-2f58d7881a5c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "534ea658-ea94-4d4c-a4e3-5d5fa1c699b6": {
      "main": [
        [
          {
            "node": "c9bfe847-7215-4ae5-a61e-4eb24ae1da0c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f25d680c-28ad-43f5-96c8-0f022cf1a710": {
      "main": [
        [
          {
            "node": "b07b40c1-4c8c-4c35-aa07-be7025ed68b2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "17d67f83-8300-41c5-a3ac-9b7ea4bc25c2": {
      "main": [
        [
          {
            "node": "534ea658-ea94-4d4c-a4e3-5d5fa1c699b6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "50792985-2a29-4aeb-8191-2a1ef3d7ec97": {
      "main": [
        [
          {
            "node": "17d67f83-8300-41c5-a3ac-9b7ea4bc25c2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Avanzado - Creación de contenido, IA Multimodal

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Flujos de trabajo relacionados recomendados

Información del flujo de trabajo
Nivel de dificultad
Avanzado
Número de nodos19
Categoría2
Tipos de nodos10
Descripción de la dificultad

Adecuado para usuarios avanzados, flujos de trabajo complejos con 16+ nodos

Autor
Nikan Noorafkan

Nikan Noorafkan

@nikkannoora

Hey, I’m Nikan Noorafkan — a creator passionate about building smart, automated workflows that drive business outcomes. With a background in performance marketing, user acquisition, and retention strategies, I use n8n to connect data, automate repetitive tasks, and scale growth across the funnel.

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34