Optimisation automatique des textes publicitaires Google avec Channable Feed et Relevance AI
Ceci est unContent Creation, Multimodal AIworkflow d'automatisation du domainecontenant 16 nœuds.Utilise principalement des nœuds comme Code, Slack, HttpRequest, GoogleSheets, SplitInBatches. Optimisation automatique des publicités Google avec les flux Channable et Relevance AI
- •Token Bot Slack ou URL Webhook
- •Peut nécessiter les informations d'identification d'authentification de l'API cible
- •Informations d'identification Google Sheets API
Nœuds utilisés (16)
Catégorie
{
"meta": {
"instanceId": "04fd795d32aabb18b913b4a3350b5cd0e9313a422ea0e7bdac0da2fb76cac9f7",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "cdb4f09e-e52a-4d5f-ad12-519db50c1234",
"name": "Déclencheur Mensuel",
"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": "Obtenir les Données de Performance des Annonces 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": "Calculer les Métriques de Performance",
"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": "Analyse de Performance par 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": "Mettre à Jour la Base de Connaissances",
"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": "Obtenir le Flux Produit Mis à Jour",
"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": "Diviser en Lots",
"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": "Régénérer les Textes d'Annonce avec 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": "Enregistrer les Annonces Optimisées dans 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": "Générer le Rapport de Performance",
"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": "Envoyer le Rapport de Performance par Email",
"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": "Note Adhésive",
"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": "Note Adhésive1",
"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": "Note Adhésive2",
"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": "Note Adhésive3",
"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": "Note Adhésive4",
"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
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Avancé - Création de contenu, IA Multimodale
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
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.
Partager ce workflow