This workflow follows the HTTP Request → Itemlists 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": "W_AD_MANAGER",
"active": true,
"settings": {
"executionTimeout": 300,
"saveExecutionProgress": true,
"saveManualExecutions": true
},
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 4
}
]
}
},
"id": "trigger",
"name": "A1 \u2014 Trigger Every 4h",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
0,
0
]
},
{
"parameters": {
"url": "={{ $env.STRAPI_INTERNAL_URL || 'http://strapi:1337' }}/api/ad-campaigns?filters[status][$eq]=active",
"method": "GET",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $env.STRAPI_API_TOKEN }}"
}
]
}
},
"id": "fetch-campaigns",
"name": "A2 \u2014 Fetch Active Campaigns",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
200,
0
]
},
{
"parameters": {
"fieldToSplitOut": "data",
"options": {}
},
"id": "item-lists",
"name": "A3 \u2014 Split Campaigns",
"type": "n8n-nodes-base.itemLists",
"typeVersion": 1,
"position": [
400,
0
]
},
{
"parameters": {
"url": "={{ $env.STRAPI_INTERNAL_URL || 'http://strapi:1337' }}/api/orders?filters[attributed_campaign][$eq]={{ $json.attributes.name }}",
"method": "GET",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $env.STRAPI_API_TOKEN }}"
}
]
}
},
"id": "fetch-orders",
"name": "A4 \u2014 Fetch Attributed Orders",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
600,
0
]
},
{
"parameters": {
"language": "javascript",
"jsCode": "const campaign = $('A3 \u2014 Split Campaigns').item.json.attributes;\nconst orders = $input.item.json.data || [];\n\nlet revenueCents = 0;\nfor (const o of orders) {\n revenueCents += (o.attributes.total_amount * 100); // converting to DA cents approx if needed, wait Strapi gives precise amount.\n // Assuming total_amount is raw value. Let's just sum it.\n}\n\n// We assume spend is daily_budget_cents * days_active\nconst launchedAt = new Date(campaign.launched_at || campaign.createdAt);\nconst daysActive = Math.max(1, (new Date() - launchedAt) / (1000 * 60 * 60 * 24));\nconst totalSpendDZD = (campaign.daily_budget_cents * daysActive) / 100;\nconst revenueDZD = revenueCents / 100;\n\nconst roas = totalSpendDZD > 0 ? (revenueDZD / totalSpendDZD) : 0;\n\n// Decisional Logic\nlet newStatus = campaign.status;\nlet autoPaused = false;\n\nif (daysActive > 2 && roas < 1.0) {\n newStatus = 'paused';\n autoPaused = true;\n}\n\nreturn [{\n json: {\n id: $('A3 \u2014 Split Campaigns').item.json.id,\n name: campaign.name,\n revenueDZD,\n totalSpendDZD,\n roas,\n newStatus,\n autoPaused\n }\n}];"
},
"id": "calc-roas",
"name": "A5 \u2014 Calculate ROAS",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
800,
0
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.autoPaused }}",
"value2": true
}
]
}
},
"id": "if-paused",
"name": "A6 \u2014 If ROI < 1.0",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
1000,
0
]
},
{
"parameters": {
"url": "={{ $env.STRAPI_INTERNAL_URL || 'http://strapi:1337' }}/api/ad-campaigns/{{ $json.id }}",
"method": "PUT",
"sendBody": true,
"contentType": "json",
"jsonBody": "={{\n JSON.stringify({\n data: {\n status: 'paused',\n auto_paused: true,\n roas: $json.roas,\n spend_cents: Math.floor($json.totalSpendDZD * 100)\n }\n })\n}}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $env.STRAPI_API_TOKEN }}"
}
]
}
},
"id": "auto-pause",
"name": "A7 \u2014 Auto Pause & Update",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
1200,
-100
]
},
{
"parameters": {
"url": "={{ $env.STRAPI_INTERNAL_URL || 'http://strapi:1337' }}/api/ad-campaigns/{{ $json.id }}",
"method": "PUT",
"sendBody": true,
"contentType": "json",
"jsonBody": "={{\n JSON.stringify({\n data: {\n roas: $json.roas,\n spend_cents: Math.floor($json.totalSpendDZD * 100)\n }\n })\n}}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $env.STRAPI_API_TOKEN }}"
}
]
}
},
"id": "update-roas",
"name": "A8 \u2014 Update live ROAS",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
1200,
100
]
}
],
"connections": {
"A1 \u2014 Trigger Every 4h": {
"main": [
[
{
"node": "A2 \u2014 Fetch Active Campaigns",
"type": "main",
"index": 0
}
]
]
},
"A2 \u2014 Fetch Active Campaigns": {
"main": [
[
{
"node": "A3 \u2014 Split Campaigns",
"type": "main",
"index": 0
}
]
]
},
"A3 \u2014 Split Campaigns": {
"main": [
[
{
"node": "A4 \u2014 Fetch Attributed Orders",
"type": "main",
"index": 0
}
]
]
},
"A4 \u2014 Fetch Attributed Orders": {
"main": [
[
{
"node": "A5 \u2014 Calculate ROAS",
"type": "main",
"index": 0
}
]
]
},
"A5 \u2014 Calculate ROAS": {
"main": [
[
{
"node": "A6 \u2014 If ROI < 1.0",
"type": "main",
"index": 0
}
]
]
},
"A6 \u2014 If ROI < 1.0": {
"main": [
[
{
"node": "A7 \u2014 Auto Pause & Update",
"type": "main",
"index": 0
}
],
[
{
"node": "A8 \u2014 Update live ROAS",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
W_AD_MANAGER. Uses httpRequest, itemLists. Scheduled trigger; 8 nodes.
Source: https://github.com/zerAda/RestaurantAgentAutomation/blob/41a4d42dcd66e57b1e87b4750c0fd5fbf7058f68/workflows/W_AD_MANAGER.json — 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.
Job seekers, career coaches, and developers looking to automate job market research and identify the exact technical skills required to land their target roles.
Master Agent - Orchestrator. Uses httpRequest, telegram, telegramTrigger. Scheduled trigger; 46 nodes.
Reputation Engine — Content Research Agent. Uses httpRequest. Scheduled trigger; 45 nodes.
Master Agent - Orchestrator. Uses httpRequest, telegram, telegramTrigger. Scheduled trigger; 43 nodes.
Linkedin Workflow. Uses httpRequest, googleSheets. Scheduled trigger; 39 nodes.