This workflow follows the Agent → HTTP Request 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 →
{
"name": "CliquezDanser_Ads_Optimization",
"nodes": [
{
"id": "CronSchedule",
"name": "Daily Schedule",
"type": "n8n-nodes-base.cron",
"typeVersion": 1,
"position": [
-720,
-180
],
"parameters": {
"triggerTimes": {
"item": [
{
"hour": 6,
"minute": 0
}
]
}
}
},
{
"id": "TelegramTrigger",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1,
"position": [
-1000,
180
],
"parameters": {
"updates": [
"message"
]
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"id": "IfVoice",
"name": "IF Voice",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
-780,
180
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json[\"message\"][\"voice\"] ? $json[\"message\"][\"voice\"][\"file_id\"] : \"\" }}",
"operation": "notEqual",
"value2": ""
}
]
}
}
},
{
"id": "TelegramDownload",
"name": "Telegram Download",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1,
"position": [
-560,
180
],
"parameters": {
"resource": "file",
"fileId": "={{ $json.message.voice.file_id }}"
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"id": "OpenAI_Transcribe",
"name": "OpenAI Transcribe",
"type": "@n8n/n8n-nodes-langchain.openAi",
"typeVersion": 1.8,
"position": [
-360,
180
],
"parameters": {
"resource": "audio",
"operation": "transcribe",
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"id": "AI_Agent_Command",
"name": "AI Agent Command",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.8,
"position": [
-140,
180
],
"parameters": {
"promptType": "define",
"text": "=Voici la transcription du message vocal:\n{{$json[\"text\"]}}\n\nSi l'utilisateur demande de \"lancer l'optimisation Google Ads\" ou \"run optimization\", renvoie un JSON:\n{\n \"run_optimization\": true\n}\nSinon:\n{\n \"run_optimization\": false\n}\n\nR\u00e9ponds uniquement en JSON.\n",
"hasOutputParser": true,
"options": {
"systemMessage": "Tu es un assistant. Lis la transcription et d\u00e9tecte si l'utilisateur veut lancer l'optimisation."
}
}
},
{
"id": "ParseCommand",
"name": "Parse Command",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
60,
180
],
"parameters": {
"functionCode": "const raw = $json[\"output\"] || \"\";\ntry {\n const data = JSON.parse(raw.replace(/```json|```/g, '').trim());\n return [{json: data}];\n} catch(e) {\n return [{json: {run_optimization: false}}];\n}"
}
},
{
"id": "IfCommand",
"name": "IF Command",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
260,
180
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json[\"run_optimization\"] }}",
"operation": "equal",
"value2": true
}
]
}
}
},
{
"id": "Merge_Triggers",
"name": "Merge Triggers",
"type": "n8n-nodes-base.merge",
"typeVersion": 1,
"position": [
-480,
-20
],
"parameters": {
"mode": "passThrough"
}
},
{
"id": "GetGoogleAdsStats",
"name": "Get Google Ads Stats",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [
-280,
-20
],
"parameters": {
"authentication": "predefinedCredentialType",
"requestMethod": "POST",
"url": "=https://googleads.googleapis.com/v14/customers/1234567890/googleAds:search",
"options": {},
"bodyParametersJson": "={\n \"query\": \"SELECT campaign.id, campaign.name, ad_group.id, ad_group.name, metrics.impressions, metrics.clicks, metrics.ctr, metrics.average_cpc, metrics.conversions, metrics.cost_micros, metrics.cost_per_conversion FROM ad_group WHERE segments.date DURING YESTERDAY\"\n}"
},
"credentials": {
"googleAdsOAuth2Api": {
"name": "<your credential>"
}
},
"continueOnFail": true
},
{
"id": "CalculateROI",
"name": "Calculate ROI",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
-80,
-20
],
"parameters": {
"functionCode": "const data = $json.results || [];\nconst VAL_CLIENT = 50;\n\nreturn data.map(row => {\n const campaignId = row.campaign?.id || row[\"campaign.id\"];\n const campaignName = row.campaign?.name || row[\"campaign.name\"];\n const adGroupId = row.adGroup?.id || row[\"ad_group.id\"];\n const adGroupName = row.adGroup?.name || row[\"ad_group.name\"];\n const costMicros = row.metrics?.costMicros || row[\"metrics.cost_micros\"] || 0;\n const costEur = costMicros / 1e6;\n const conv = row.metrics?.conversions || row[\"metrics.conversions\"] || 0;\n let roi = 0;\n if (costEur > 0) {\n roi = ((conv * VAL_CLIENT) - costEur) / costEur;\n }\n const costPerConvMicros = row.metrics?.costPerConversion || row[\"metrics.cost_per_conversion\"] || 0;\n const costPerConvEur = costPerConvMicros / 1e6;\n return {\n campaign_id: campaignId,\n campaign_name: campaignName,\n ad_group_id: adGroupId,\n ad_group_name: adGroupName,\n impressions: row.metrics?.impressions || 0,\n clicks: row.metrics?.clicks || 0,\n ctr: (row.metrics?.ctr || 0) * 100,\n cost_eur: parseFloat(costEur.toFixed(2)),\n conversions: conv,\n cost_per_conv_eur: parseFloat(costPerConvEur.toFixed(2)),\n roi: parseFloat(roi.toFixed(2))\n };\n});"
}
},
{
"id": "AI_Agent_Analysis",
"name": "AI Agent Analysis",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.8,
"position": [
120,
-20
],
"parameters": {
"promptType": "define",
"text": "=Voici les stats:\n{{$json}}\n\nR\u00e8gles:\n- Valeur client = 50\u20ac\n- ROI = ((Conversions*50) - Cost) / Cost\n- Si ROI < 1 ou cost/conv > 20 => Action = Decrease\n- Si ROI > 3 ou cost/conv < 10 => Action = Increase\n- Sinon => NoChange\n\nR\u00e9ponds en JSON, par ex:\n{\n \"action\": \"decrease\",\n \"explanation\": \"...\"\n}\n\nPour chaque item, renvoie un array:\n[\n {\"ad_group_id\":..., \"action\":\"increase/decrease/nochange\", \"explanation\":\"...\"}, ...\n]\n"
}
},
{
"id": "ParseAIOutput",
"name": "Parse AI Output",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
320,
-20
],
"parameters": {
"functionCode": "const raw = $json[\"output\"] || \"\";\ntry {\n const data = JSON.parse(raw.replace(/```json|```/g, '').trim());\n return data.map(d => ({json: d}));\n} catch(e) {\n return [];\n}"
}
},
{
"id": "IfIncrease",
"name": "If Increase",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
520,
-140
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json[\"action\"] }}",
"operation": "equal",
"value2": "increase"
}
]
}
}
},
{
"id": "IfDecrease",
"name": "If Decrease",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
520,
60
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json[\"action\"] }}",
"operation": "equal",
"value2": "decrease"
}
]
}
}
},
{
"id": "HTTP_Increase",
"name": "HTTP Increase Bid",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [
720,
-200
],
"parameters": {
"authentication": "predefinedCredentialType",
"requestMethod": "POST",
"url": "=https://googleads.googleapis.com/v14/customers/1234567890/adGroups:mutate",
"bodyParametersJson": "={\n \"operations\": [\n {\n \"update\": {\n \"resourceName\": \"customers/1234567890/adGroups/{{ $json[\\\"ad_group_id\\\"] }}\",\n \"cpcBidMicros\": 12300000\n },\n \"updateMask\": \"cpcBidMicros\"\n }\n ]\n}"
},
"credentials": {
"googleAdsOAuth2Api": {
"name": "<your credential>"
}
},
"continueOnFail": true
},
{
"id": "HTTP_Decrease",
"name": "HTTP Decrease Bid",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [
720,
120
],
"parameters": {
"authentication": "predefinedCredentialType",
"requestMethod": "POST",
"url": "=https://googleads.googleapis.com/v14/customers/1234567890/adGroups:mutate",
"bodyParametersJson": "={\n \"operations\": [\n {\n \"update\": {\n \"resourceName\": \"customers/1234567890/adGroups/{{ $json[\\\"ad_group_id\\\"] }}\",\n \"cpcBidMicros\": 8700000\n },\n \"updateMask\": \"cpcBidMicros\"\n }\n ]\n}"
},
"credentials": {
"googleAdsOAuth2Api": {
"name": "<your credential>"
}
},
"continueOnFail": true
},
{
"id": "AsanaLog",
"name": "Asana Log",
"type": "n8n-nodes-base.asana",
"typeVersion": 1,
"position": [
900,
-40
],
"parameters": {
"resource": "task",
"operation": "create",
"workspace": "",
"name": "={{ \"[CliquezDansez] \" + ($json[\"action\"] === \"increase\" ? \"Augmentation\" : \"Diminution\") + \" ench\u00e8re\" }}",
"additionalFields": {
"notes": "=Date: {{ new Date().toISOString().slice(0,10) }}\nAd Group: {{ $json[\"ad_group_id\"] }}\nAction: {{ $json[\"action\"] }}\nExplication: {{ $json[\"explanation\"] || \"\" }}",
"projects": [
"Cliquezdansez"
]
}
},
"credentials": {
"asanaApi": {
"name": "<your credential>"
}
}
},
{
"id": "SendTelegramResult",
"name": "Send Telegram Result",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1,
"position": [
1100,
-40
],
"parameters": {
"chatId": "",
"text": "={{ \"Ajustement effectu\u00e9 pour adGroup=\" + $json[\"ad_group_id\"] + \", action=\" + $json[\"action\"] }}",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Daily Schedule": {
"main": [
[
{
"node": "Set Constants",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "IfVoice",
"type": "main",
"index": 0
}
]
]
},
"IfVoice": {
"main": [
[
{
"node": "TelegramDownload",
"type": "main",
"index": 0
}
],
[]
]
},
"TelegramDownload": {
"main": [
[
{
"node": "OpenAI_Transcribe",
"type": "main",
"index": 0
}
]
]
},
"OpenAI_Transcribe": {
"main": [
[
{
"node": "AI_Agent_Command",
"type": "main",
"index": 0
}
]
]
},
"AI_Agent_Command": {
"main": [
[
{
"node": "ParseCommand",
"type": "main",
"index": 0
}
]
]
},
"ParseCommand": {
"main": [
[
{
"node": "IF Command",
"type": "main",
"index": 0
}
]
]
},
"IF Command": {
"main": [
[
{
"node": "Merge Triggers",
"type": "main",
"index": 0
}
],
[]
]
},
"Set Constants": {
"main": [
[
{
"node": "Merge Triggers",
"type": "main",
"index": 0
}
]
]
},
"Merge Triggers": {
"main": [
[
{
"node": "GetGoogleAdsStats",
"type": "main",
"index": 0
}
]
]
},
"GetGoogleAdsStats": {
"main": [
[
{
"node": "CalculateROI",
"type": "main",
"index": 0
}
]
]
},
"CalculateROI": {
"main": [
[
{
"node": "AI Agent Analysis",
"type": "main",
"index": 0
}
]
]
},
"AI Agent Analysis": {
"main": [
[
{
"node": "ParseAIOutput",
"type": "main",
"index": 0
}
]
]
},
"ParseAIOutput": {
"main": [
[
{
"node": "IfIncrease",
"type": "main",
"index": 0
},
{
"node": "IfDecrease",
"type": "main",
"index": 1
}
]
]
},
"IfIncrease": {
"main": [
[
{
"node": "HTTP Increase Bid",
"type": "main",
"index": 0
},
{
"node": "AsanaLog",
"type": "main",
"index": 0
},
{
"node": "SendTelegramResult",
"type": "main",
"index": 0
}
],
[]
]
},
"IfDecrease": {
"main": [
[
{
"node": "HTTP Decrease Bid",
"type": "main",
"index": 0
},
{
"node": "AsanaLog",
"type": "main",
"index": 0
},
{
"node": "SendTelegramResult",
"type": "main",
"index": 0
}
],
[]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"id": "CliquezDanser_Ads_Optimization_Final",
"tags": []
}
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.
asanaApigoogleAdsOAuth2ApiopenAiApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
CliquezDanser_Ads_Optimization. Uses telegramTrigger, telegram, openAi, agent. Scheduled trigger; 19 nodes.
Source: https://gist.github.com/Igor1402-star/7c076cc0dfb8581ec53318827c421373 — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Template Name: AI Personal Assistant - Task & Email Management Price: $27 Category: Productivity & Automation Difficulty: Intermediate Use Case: Personal productivity automation for busy professionals
Title: Create daily AI news digest and send to Telegram
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
Generate AI viral videos with NanoBanana & VEO3, shared on socials via Blotato 2. Uses @blotato/n8n-nodes-blotato, googleSheets, lmChatOpenAi, toolThink. Event-driven trigger; 94 nodes.
AI Agent Workflow. Uses telegramTrigger, chatTrigger, telegram, openAi. Event-driven trigger; 82 nodes.