Automatisierung von Google Ads-Anzeigentexten mit Channable Feed und Relevance AI
Dies ist ein Content Creation, Multimodal AI-Bereich Automatisierungsworkflow mit 16 Nodes. Hauptsächlich werden Code, Slack, HttpRequest, GoogleSheets, SplitInBatches und andere Nodes verwendet. Automatisierung der Google Ads-Anzeigentext-Optimierung mit Channable Feed und Relevance AI
- •Slack Bot Token oder Webhook URL
- •Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
- •Google Sheets API-Anmeldedaten
Verwendete Nodes (16)
Kategorie
{
"meta": {
"instanceId": "04fd795d32aabb18b913b4a3350b5cd0e9313a422ea0e7bdac0da2fb76cac9f7",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "cdb4f09e-e52a-4d5f-ad12-519db50c1234",
"name": "Monatlicher Zeitplan-Trigger",
"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": "Google Anzeigenleistungsdaten abrufen",
"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": "Leistungskennzahlen berechnen",
"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": "KI-Leistungsanalyse",
"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": "Wissensdatenbank aktualisieren",
"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": "Aktualisierten Produktfeed abrufen",
"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": "In Batches aufteilen",
"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": "Anzeigentext mit Erkenntnissen neu generieren",
"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": "Optimierte Anzeigen in Sheets speichern",
"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": "Leistungsbericht erstellen",
"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": "Leistungsbericht per E-Mail senden",
"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": "Notizzettel",
"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": "Notizzettel1",
"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": "Notizzettel2",
"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": "Notizzettel3",
"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": "Notizzettel4",
"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
}
]
]
}
}
}Wie verwende ich diesen Workflow?
Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.
Für welche Szenarien ist dieser Workflow geeignet?
Experte - Content-Erstellung, Multimodales KI
Ist es kostenpflichtig?
Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.
Verwandte Workflows
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.
Diesen Workflow teilen