Optimización automatizada de textos publicitarios de Google Ads con Channable Feed y Relevance AI
Este es unContent Creation, Multimodal AIflujo de automatización del dominio deautomatización que contiene 16 nodos.Utiliza principalmente nodos como Code, Slack, HttpRequest, GoogleSheets, SplitInBatches. Optimización automática de copias de anuncios de Google usando Channable Feed y Relevance AI
- •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
Nodos utilizados (16)
Categoría
{
"meta": {
"instanceId": "04fd795d32aabb18b913b4a3350b5cd0e9313a422ea0e7bdac0da2fb76cac9f7",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "cdb4f09e-e52a-4d5f-ad12-519db50c1234",
"name": "Activador de programación mensual",
"type": "n8n-nodes-base.scheduleTrigger",
"notes": "Triggers on 1st of every month at midnight for 30-day performance review",
"position": [
300,
1720
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 0 1 * *"
}
]
}
},
"typeVersion": 1
},
{
"id": "8e3a3528-4cce-49c8-8b9d-412d24a5a595",
"name": "Obtener datos de rendimiento de anuncios Google",
"type": "n8n-nodes-base.httpRequest",
"notes": "CORRECTED: Uses HTTP Request with GAQL query instead of limited native Google Ads node. Returns all ads with min 100 impressions for statistical validity.",
"position": [
660,
1740
],
"parameters": {
"url": "=https://googleads.googleapis.com/{{$env.GOOGLE_ADS_API_VERSION}}/customers/{{$env.GOOGLE_ADS_CUSTOMER_ID}}/googleAds:search",
"method": "POST",
"options": {
"timeout": 60000
},
"jsonBody": "={\n \"query\": \"SELECT ad_group_ad.ad.id, ad_group_ad.ad.responsive_search_ad.headlines, ad_group_ad.ad.responsive_search_ad.descriptions, ad_group.name, campaign.name, metrics.impressions, metrics.clicks, metrics.ctr, metrics.conversions, metrics.cost_micros FROM ad_group_ad WHERE segments.date DURING LAST_30_DAYS AND metrics.impressions > 100 ORDER BY metrics.clicks DESC LIMIT 10000\"\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleAdsOAuth2Api"
},
"credentials": {
"googleAdsOAuth2Api": {
"id": "x3Atp2GWGOjlhMz9",
"name": "Google Ads account"
}
},
"typeVersion": 4.2
},
{
"id": "78baf9e9-5e1b-424c-ac5c-6bf33c3a9fa5",
"name": "Calcular métricas de rendimiento",
"type": "n8n-nodes-base.code",
"notes": "Analyzes GAQL response to identify patterns by category and theme. Calculates CTR, conversion rates, top/bottom performers.",
"position": [
1060,
1760
],
"parameters": {
"jsCode": "// Calculate performance metrics and identify patterns\n\nconst items = $input.all();\nconst results = items[0].json.results || [];\n\n// Group ads by category and theme\nconst categoryPerformance = {};\nconst themePerformance = {};\n\nresults.forEach(result => {\n const adGroup = result.adGroup?.name || 'Unknown';\n const headlines = result.adGroupAd?.ad?.responsiveSearchAd?.headlines || [];\n const headline = headlines[0]?.text || '';\n const ctr = parseFloat(result.metrics?.ctr || 0);\n const impressions = parseInt(result.metrics?.impressions || 0);\n const clicks = parseInt(result.metrics?.clicks || 0);\n const conversions = parseFloat(result.metrics?.conversions || 0);\n const cost = parseFloat(result.metrics?.costMicros || 0) / 1000000;\n \n // Only include ads with sufficient data\n if (impressions < 100) return;\n \n // Aggregate by category (ad group)\n if (!categoryPerformance[adGroup]) {\n categoryPerformance[adGroup] = {\n total_impressions: 0,\n total_clicks: 0,\n total_conversions: 0,\n total_cost: 0,\n ad_count: 0\n };\n }\n \n categoryPerformance[adGroup].total_impressions += impressions;\n categoryPerformance[adGroup].total_clicks += clicks;\n categoryPerformance[adGroup].total_conversions += conversions;\n categoryPerformance[adGroup].total_cost += cost;\n categoryPerformance[adGroup].ad_count += 1;\n \n // Extract themes from headlines\n const themes = ['vegan', 'organic', 'natural', 'premium', 'budget', 'sale', 'new', 'bestseller', 'free shipping'];\n const headlineLower = headline.toLowerCase();\n \n themes.forEach(theme => {\n if (headlineLower.includes(theme)) {\n if (!themePerformance[theme]) {\n themePerformance[theme] = {\n total_impressions: 0,\n total_clicks: 0,\n total_conversions: 0,\n ad_count: 0\n };\n }\n themePerformance[theme].total_impressions += impressions;\n themePerformance[theme].total_clicks += clicks;\n themePerformance[theme].total_conversions += conversions;\n themePerformance[theme].ad_count += 1;\n }\n });\n});\n\n// Calculate averages\nconst categoryMetrics = Object.entries(categoryPerformance).map(([category, data]) => ({\n category,\n avg_ctr: ((data.total_clicks / data.total_impressions) * 100).toFixed(2),\n total_impressions: data.total_impressions,\n total_clicks: data.total_clicks,\n conversion_rate: data.total_clicks > 0 ? ((data.total_conversions / data.total_clicks) * 100).toFixed(2) : '0.00',\n avg_cost_per_click: data.total_clicks > 0 ? (data.total_cost / data.total_clicks).toFixed(2) : '0.00',\n ad_count: data.ad_count\n}));\n\nconst themeMetrics = Object.entries(themePerformance).map(([theme, data]) => ({\n theme,\n avg_ctr: ((data.total_clicks / data.total_impressions) * 100).toFixed(2),\n total_impressions: data.total_impressions,\n total_clicks: data.total_clicks,\n conversion_rate: data.total_clicks > 0 ? ((data.total_conversions / data.total_clicks) * 100).toFixed(2) : '0.00',\n ad_count: data.ad_count\n}));\n\n// Sort by CTR\ncategoryMetrics.sort((a, b) => parseFloat(b.avg_ctr) - parseFloat(a.avg_ctr));\nthemeMetrics.sort((a, b) => parseFloat(b.avg_ctr) - parseFloat(a.avg_ctr));\n\n// Identify top 20% and bottom 20%\nconst topCategories = categoryMetrics.slice(0, Math.max(1, Math.ceil(categoryMetrics.length * 0.2)));\nconst bottomCategories = categoryMetrics.slice(-Math.max(1, Math.ceil(categoryMetrics.length * 0.2)));\n\nconst topThemes = themeMetrics.slice(0, Math.max(1, Math.ceil(themeMetrics.length * 0.2)));\nconst bottomThemes = themeMetrics.slice(-Math.max(1, Math.ceil(themeMetrics.length * 0.2)));\n\nreturn {\n overall_metrics: {\n total_ads_analyzed: results.length,\n date_range: 'Last 30 days',\n analysis_date: new Date().toISOString()\n },\n category_performance: categoryMetrics,\n theme_performance: themeMetrics,\n top_performers: {\n categories: topCategories,\n themes: topThemes\n },\n bottom_performers: {\n categories: bottomCategories,\n themes: bottomThemes\n }\n};"
},
"typeVersion": 2
},
{
"id": "d5ad62d0-fff7-4d75-8ca4-128f21a3183c",
"name": "Análisis de rendimiento con IA",
"type": "n8n-nodes-base.httpRequest",
"notes": "CORRECTED: Uses /agents/trigger with agent_id. AI analyzes patterns and provides insights like 'vegan messaging +23% CTR vs natural'.",
"position": [
1560,
1660
],
"parameters": {
"url": "={{$env.RELEVANCE_AI_API_URL}}/agents/trigger",
"method": "POST",
"options": {
"timeout": 90000
},
"jsonBody": "={\n \"message\": {\n \"role\": \"user\",\n \"content\": \"Analyze this performance data and provide actionable insights. Data: \" + JSON.stringify($json)\n },\n \"agent_id\": \"{{$env.RELEVANCE_AGENT_PERFORMANCE_ID}}\"\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "luTyM3gZSgwhM8i0",
"name": "Header Auth account"
}
},
"typeVersion": 4.2
},
{
"id": "15b0f40c-3422-47f6-b8d8-e901444e5209",
"name": "Actualizar base de conocimiento",
"type": "n8n-nodes-base.httpRequest",
"notes": "CORRECTED: Uses knowledge source ID from env var. Feeds insights to Relevance AI for future ad generation.",
"position": [
1840,
1660
],
"parameters": {
"url": "={{$env.RELEVANCE_AI_API_URL}}/knowledge/{{$env.RELEVANCE_KNOWLEDGE_SOURCE_ID}}/update",
"method": "POST",
"options": {},
"jsonBody": "={\n \"data\": {\n \"insights\": {{JSON.stringify($json.insights || $json.output)}},\n \"updated_at\": \"{{$now.toISO()}}\",\n \"top_themes\": {{JSON.stringify($node['Calculate Performance Metrics'].json.top_performers.themes)}}\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "luTyM3gZSgwhM8i0",
"name": "Header Auth account"
}
},
"typeVersion": 4.2
},
{
"id": "d9352d9b-16d9-45e2-9ed5-294d49d2faee",
"name": "Obtener feed de productos actualizado",
"type": "n8n-nodes-base.httpRequest",
"notes": "Retrieves latest product feed for regenerating ads with performance insights",
"position": [
2140,
1660
],
"parameters": {
"url": "={{$env.CHANNABLE_API_URL}}/companies/{{$env.CHANNABLE_COMPANY_ID}}/projects/{{$env.CHANNABLE_PROJECT_ID}}/feeds/{{$env.FEED_ID}}",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "luTyM3gZSgwhM8i0",
"name": "Header Auth account"
}
},
"typeVersion": 4.2
},
{
"id": "2a185395-90da-4a6c-a951-9cc8308df67e",
"name": "Dividir en lotes",
"type": "n8n-nodes-base.splitInBatches",
"notes": "Process 50 products at a time",
"position": [
2460,
1660
],
"parameters": {
"options": {},
"batchSize": 50
},
"typeVersion": 3
},
{
"id": "7e26aa2c-0630-43c6-80a3-6e873d8614bb",
"name": "Regenerar textos de anuncios con insights",
"type": "n8n-nodes-base.httpRequest",
"notes": "CORRECTED: Uses /trigger endpoint. AI now automatically uses performance insights from knowledge base.",
"position": [
2760,
1660
],
"parameters": {
"url": "={{$env.RELEVANCE_AI_API_URL}}/tools/{{$env.RELEVANCE_TOOL_AD_COPY_ID}}/trigger",
"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 \"use_performance_insights\": true\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "luTyM3gZSgwhM8i0",
"name": "Header Auth account"
}
},
"typeVersion": 4.2
},
{
"id": "9645459f-f2fe-4bd1-abdc-b393a2d0282d",
"name": "Guardar anuncios optimizados en Sheets",
"type": "n8n-nodes-base.googleSheets",
"notes": "CORRECTED: Saves optimized ads to Google Sheets for review before publishing",
"position": [
3120,
1660
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Optimized Ads"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{$env.GOOGLE_SHEET_ID}}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "0xHwEMloLvs9YH5S",
"name": "Google Sheets account"
}
},
"typeVersion": 4.4
},
{
"id": "e5484057-503a-4cf5-968c-000c64b0fd04",
"name": "Generar informe de rendimiento",
"type": "n8n-nodes-base.code",
"notes": "Creates detailed performance report with insights and changes made",
"position": [
3480,
1660
],
"parameters": {
"jsCode": "// Generate performance report\nconst performanceData = $node['AI Performance Analysis'].json;\nconst metricsData = $node['Calculate Performance Metrics'].json;\n\nconst topThemes = metricsData.top_performers?.themes || [];\nconst bottomThemes = metricsData.bottom_performers?.themes || [];\n\nconst report = `# 30-Day Performance Optimization Report\n\n## Executive Summary\nDate: ${new Date().toISOString().split('T')[0]}\nAnalysis Period: Last 30 days\nAds Analyzed: ${metricsData.overall_metrics?.total_ads_analyzed || 0}\n\n## Top Performing Themes\n${topThemes.map((t, i) => `${i+1}. ${t.theme}: ${t.avg_ctr}% CTR (${t.ad_count} ads)`).join('\\n')}\n\n## Underperforming Themes\n${bottomThemes.map((t, i) => `${i+1}. ${t.theme}: ${t.avg_ctr}% CTR (${t.ad_count} ads)`).join('\\n')}\n\n## AI Insights\n${performanceData.output || performanceData.insights || 'Analysis complete'}\n\n## Next Optimization Cycle\nScheduled for: ${new Date(Date.now() + 30*24*60*60*1000).toISOString().split('T')[0]}\n`;\n\nreturn {\n report_text: report,\n report_html: report.replace(/\\n/g, '<br>'),\n generated_at: new Date().toISOString(),\n top_themes: topThemes,\n bottom_themes: bottomThemes\n};"
},
"typeVersion": 2
},
{
"id": "f3096b96-3daa-4eee-bd52-666d5edb9d21",
"name": "Enviar informe de rendimiento por correo",
"type": "n8n-nodes-base.slack",
"notes": "Sends performance report to team",
"position": [
3740,
1660
],
"webhookId": "7f13c699-7b46-4800-a05f-708e317c3f48",
"parameters": {
"text": "={{$json.report_text}}",
"otherOptions": {}
},
"typeVersion": 2.1
},
{
"id": "4dfc8a9d-039e-457e-96df-12811d2e5afb",
"name": "Nota adhesiva",
"type": "n8n-nodes-base.stickyNote",
"position": [
-860,
1600
],
"parameters": {
"width": 1040,
"height": 240,
"content": "# 🧠 Google Ads Monthly Optimization (Channable + Google Ads + Relevance AI)\nAutomates your monthly Google Ads optimization using Relevance AI and Channable. \nAnalyzes ad performance, identifies top/bottom performers, generates AI insights, and refreshes ad copies with data-driven improvements.\n"
},
"typeVersion": 1
},
{
"id": "d6c75f5e-bd70-46c8-b02f-48176f69b347",
"name": "Nota adhesiva1",
"type": "n8n-nodes-base.stickyNote",
"position": [
280,
1920
],
"parameters": {
"width": 960,
"content": "## 🟨 Stage 1 — Data Collection & Trigger\n| ⏰ Monthly Schedule Trigger | 📊 Get Google Ads Performance Data | 🧮 Calculate Performance Metrics |\n|-----------------------------|-----------------------------------|--------------------------------|\n| Runs automatically on the 1st of each month at midnight to review the past 30 days. | Retrieves Google Ads data using GAQL via the API — includes impressions, clicks, CTR, conversions, and costs. | Processes raw data to compute performance metrics (CTR, conversion rate, CPC). Groups results by ad category and creative theme. |"
},
"typeVersion": 1
},
{
"id": "c0bca487-73de-4b13-89dc-de8a59e3bdca",
"name": "Nota adhesiva2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1400,
1400
],
"parameters": {
"width": 960,
"content": "## 🟨 Stage 2 — AI Analysis & Knowledge Update\n| 🤖 AI Performance Analysis | 🧠 Update Knowledge Base | 📦 Get Updated Product Feed |\n|----------------------------|--------------------------|-----------------------------|\n| Uses Relevance AI’s `/agents/trigger` endpoint to analyze metrics and extract actionable insights. Example: *“Vegan-themed ads show +23% CTR vs average.”* | Feeds AI-generated insights back into your Relevance AI knowledge base for future ad optimization cycles. | Retrieves the latest Channable product feed to prepare updated ads using the new performance insights. |"
},
"typeVersion": 1
},
{
"id": "65852982-9233-491d-b9ab-2a25cb712056",
"name": "Nota adhesiva3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2400,
1880
],
"parameters": {
"width": 940,
"height": 140,
"content": "## 🟨 Stage 3 — Ad Copy Regeneration & Storage\n| ✂️ Split Into Batches | ✍️ Regenerate Ad Copy with Insights | 📄 Save Optimized Ads to Sheets |\n|------------------------|------------------------------------|--------------------------------|\n| Splits the product feed into batches of 50 to optimize efficiently. | Uses Relevance AI `/tools/{id}/trigger` to rewrite ad copy for each product, incorporating fresh performance data. | Saves regenerated ads to a Google Sheet for QA review or manual approval before publishing. |"
},
"typeVersion": 1
},
{
"id": "de84f6a1-a333-4df9-b6a4-d9684396596d",
"name": "Nota adhesiva4",
"type": "n8n-nodes-base.stickyNote",
"position": [
3980,
1640
],
"parameters": {
"width": 620,
"height": 140,
"content": "## 🟨 Stage 4 — Reporting & Communication\n| 📈 Generate Performance Report | 📢 Email Performance Report |\n|-------------------------------|-----------------------------|\n| Generates a comprehensive monthly performance report summarizing top/bottom themes, CTR trends, and AI recommendations. | Sends a Slack message (or email) to the marketing team containing the full report and optimization insights. |"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"2a185395-90da-4a6c-a951-9cc8308df67e": {
"main": [
[
{
"node": "7e26aa2c-0630-43c6-80a3-6e873d8614bb",
"type": "main",
"index": 0
}
]
]
},
"15b0f40c-3422-47f6-b8d8-e901444e5209": {
"main": [
[
{
"node": "d9352d9b-16d9-45e2-9ed5-294d49d2faee",
"type": "main",
"index": 0
}
]
]
},
"d5ad62d0-fff7-4d75-8ca4-128f21a3183c": {
"main": [
[
{
"node": "15b0f40c-3422-47f6-b8d8-e901444e5209",
"type": "main",
"index": 0
}
]
]
},
"d9352d9b-16d9-45e2-9ed5-294d49d2faee": {
"main": [
[
{
"node": "2a185395-90da-4a6c-a951-9cc8308df67e",
"type": "main",
"index": 0
}
]
]
},
"cdb4f09e-e52a-4d5f-ad12-519db50c1234": {
"main": [
[
{
"node": "8e3a3528-4cce-49c8-8b9d-412d24a5a595",
"type": "main",
"index": 0
}
]
]
},
"e5484057-503a-4cf5-968c-000c64b0fd04": {
"main": [
[
{
"node": "f3096b96-3daa-4eee-bd52-666d5edb9d21",
"type": "main",
"index": 0
}
]
]
},
"9645459f-f2fe-4bd1-abdc-b393a2d0282d": {
"main": [
[
{
"node": "e5484057-503a-4cf5-968c-000c64b0fd04",
"type": "main",
"index": 0
}
]
]
},
"78baf9e9-5e1b-424c-ac5c-6bf33c3a9fa5": {
"main": [
[
{
"node": "d5ad62d0-fff7-4d75-8ca4-128f21a3183c",
"type": "main",
"index": 0
}
]
]
},
"8e3a3528-4cce-49c8-8b9d-412d24a5a595": {
"main": [
[
{
"node": "78baf9e9-5e1b-424c-ac5c-6bf33c3a9fa5",
"type": "main",
"index": 0
}
]
]
},
"7e26aa2c-0630-43c6-80a3-6e873d8614bb": {
"main": [
[
{
"node": "9645459f-f2fe-4bd1-abdc-b393a2d0282d",
"type": "main",
"index": 0
}
]
]
}
}
}¿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
Nikan Noorafkan
@nikkannooraHey, 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.
Compartir este flujo de trabajo