This workflow corresponds to n8n.io template #15359 — we link there as the canonical source.
This workflow follows the Error Trigger → Gmail 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 →
{
"id": "rauEsTkyr7CZDotc",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Klaviyo List Decay Detection Deploy",
"tags": [],
"nodes": [
{
"id": "afc4935d-c2e3-4647-af95-142d059731c3",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-688,
-576
],
"parameters": {
"color": 7,
"width": 728,
"height": 478,
"content": "## \ud83d\udcca Klaviyo List Decay Detection\n\nAutomatically monitors your Klaviyo audience health by scoring every profile based on their last engagement date. Critical profiles (90+ days inactive) are bulk-suppressed before they damage your sender reputation.\n\n**How it works**\n1. Runs every night at 2 AM on a cron schedule\n2. Fetches all profiles from the Klaviyo API (paginated)\n3. Scores and classifies each profile into a decay tier\n4. Logs all profiles to Postgres for historical tracking\n5. Auto-suppresses critical profiles via Klaviyo's Bulk Suppression API\n6. Emails a styled HTML decay report\n\n**Decay Tiers**\n\ud83d\udfe2 **Active** \u2014 < 30 days \u00b7 No action\n\ud83d\udfe1 **Moderate Decay** \u2014 30\u201360 days \u00b7 Logged only\n\ud83d\udfe0 **High Decay** \u2014 60\u201390 days \u00b7 Logged only\n\ud83d\udd34 **Critical** \u2014 90+ days \u00b7 Auto-suppressed in Klaviyo"
},
"typeVersion": 1
},
{
"id": "1e0c9c94-0577-468e-9a27-261985cf28ce",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
80,
-576
],
"parameters": {
"color": 3,
"width": 764,
"height": 478,
"content": "## \u2699\ufe0f Setup Instructions\n\n**1. Credentials to configure**\n- **Klaviyo API Key** \u2014 Create an HTTP Header Auth credential. Header name: `Authorization`, value: `Klaviyo-API-Key <YOUR_KEY>`. Use it in the `Get All Profiles` node.\n- **Postgres** \u2014 Connect your database in `Log Profiles to DB` and `Insert Run Summary`.\n- **Gmail OAuth2** \u2014 Authorize Gmail for `Send a message` and `Send Error Alert`.\n\n**2. Environment variable**\nAdd `KLAVIYO_API_KEY` to your n8n environment settings. The suppression batch node reads it via `$env.KLAVIYO_API_KEY`.\n\n**3. Create database tables before activating**\n`klaviyo_decay_log` \u2014 one row per profile per run\nColumns: profile_id, email, days_since_active, tier, engagement_score, action_taken, run_id\n\n`klaviyo_run_summary` \u2014 one row per workflow run\nColumns: run_id, run_start, run_end, total_profiles, active_count, moderate_count, high_count, critical_count, suppressed_count, status, error_message\n\n**4. Update recipient emails** in `Send a message` and `Send Error Alert`, then activate the workflow \u2705"
},
"typeVersion": 1
},
{
"id": "9b541159-0955-4dc2-b6b9-ecdb9d0e2f85",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-656,
304
],
"parameters": {
"color": 5,
"width": 430,
"height": 254,
"content": "**1 \u2014 Trigger & Initialize**\nFires at 2 AM daily. The Set node initializes run metadata (timestamp, run ID) passed downstream for tracing."
},
"typeVersion": 1
},
{
"id": "1bdde67b-b265-40c7-a13f-6dc420243cb7",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-192,
304
],
"parameters": {
"color": 5,
"width": 440,
"height": 254,
"content": "**2 \u2014 Fetch & Extract Profiles**\nPaginates through the Klaviyo Profiles API requesting `email`, `created`, and `last_event_date`. The Code node unwraps the nested pagination envelope into flat profile items."
},
"typeVersion": 1
},
{
"id": "34758865-62fa-457c-b972-e39dc8f4abb0",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
272,
304
],
"parameters": {
"color": 5,
"width": 200,
"height": 254,
"content": "**3 \u2014 Score Profiles**\nCalculates days since last engagement. Assigns each profile a decay tier, a 0\u2013100 engagement score, and an action tag."
},
"typeVersion": 1
},
{
"id": "41274223-9d80-4305-80a0-96eb7c1f66b4",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
464,
-32
],
"parameters": {
"color": 5,
"width": 376,
"height": 222,
"content": "**4 \u2014 Log All Profiles**\nInserts every scored profile into `klaviyo_decay_log` for historical analysis and auditing."
},
"typeVersion": 1
},
{
"id": "ed934b3b-b9a7-409b-923f-bdeb906a0a8f",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
288
],
"parameters": {
"color": 5,
"width": 860,
"height": 270,
"content": "**5 \u2014 Summarize, Store & Report**\nAggregates tier counts into a single run summary row and saves it to `klaviyo_run_summary`. Builds a styled HTML email and sends the daily decay report."
},
"typeVersion": 1
},
{
"id": "a9c24f5e-035f-4a2f-8117-8bdaaa68b6fb",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
576
],
"parameters": {
"color": 3,
"width": 586,
"height": 334,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n**6 \u2014 Auto-Suppress Critical Profiles \u26a0\ufe0f**\nProfiles inactive for 90+ days are filtered here and bulk-suppressed in Klaviyo in batches of 100 using the Profile Suppression Bulk Create API. Non-critical profiles are discarded from this branch."
},
"typeVersion": 1
},
{
"id": "7ce5a20a-f9f3-4885-93df-9b4919b6e6e0",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-661,
721
],
"parameters": {
"color": 2,
"width": 938,
"height": 255,
"content": "**Error Handling**\nAny uncaught error in the main workflow triggers this path. The failure details are formatted and logged to `klaviyo_run_summary` with `status: failed`, and an alert email is sent immediately."
},
"typeVersion": 1
},
{
"id": "0be8b80c-d538-4f33-9b77-5049d898818b",
"name": "Schedule: Daily 2AM",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-576,
400
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 2 * * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "b0b310de-7ff8-41ac-a5b5-935abfd2f6bf",
"name": "Set: Initialize Run",
"type": "n8n-nodes-base.set",
"position": [
-352,
400
],
"parameters": {
"options": {}
},
"typeVersion": 3.4
},
{
"id": "39a8d5fa-f043-499b-8a3b-48746d0094f1",
"name": "Get All Profiles",
"type": "n8n-nodes-base.httpRequest",
"position": [
-128,
400
],
"parameters": {
"url": "https://a.klaviyo.com/api/profiles/",
"options": {
"pagination": {}
},
"sendQuery": true,
"sendHeaders": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "page[size]",
"value": "100"
},
{
"name": "fields[profile]",
"value": "email,created,last_event_date"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "revision",
"value": "2024-10-15"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "554f666e-9d02-4022-a624-62b78cfb9f7b",
"name": "Extract Profile Items",
"type": "n8n-nodes-base.code",
"position": [
96,
400
],
"parameters": {
"jsCode": "const profiles = [];\n\nfor (const item of $input.all()) {\n let val = item.json;\n\n // Step 1 \u00e2 n8n pagination wraps the full API response as a string in item.json.data\n if (val && typeof val.data === 'string') {\n try { val = JSON.parse(val.data); } catch (e) { val = null; }\n }\n\n // Step 2 \u00e2 parsed result is { data: [...profiles], links: {...} }; extract the array\n if (val && !Array.isArray(val) && Array.isArray(val.data)) {\n val = val.data;\n }\n\n // Step 3 \u00e2 val is now the profiles array (or a single profile object)\n if (Array.isArray(val)) {\n for (const profile of val) {\n profiles.push({ json: profile });\n }\n } else if (val && val.id) {\n profiles.push({ json: val });\n }\n}\n\nreturn profiles;\n"
},
"typeVersion": 2
},
{
"id": "e94fd26c-3ceb-4c9e-a411-4d8a410b96a7",
"name": "Score Profiles",
"type": "n8n-nodes-base.code",
"position": [
320,
400
],
"parameters": {
"jsCode": "const now = DateTime.now();\n\n// Generate a stable run_id from the execution start time.\n// Using DateTime avoids $execution.id which is not available in all n8n versions.\nconst runId = now.toFormat('yyyyMMdd-HHmmss') + '-' + Math.random().toString(36).slice(2, 8);\n\nreturn $input.all().map(item => {\n const profile = item.json;\n const attrs = profile.attributes || {};\n\n const candidates = [attrs.last_event_date, attrs.created].filter(Boolean);\n const lastEngaged = candidates.length > 0\n ? candidates.map(d => DateTime.fromISO(d)).reduce((a, b) => (a > b ? a : b))\n : null;\n\n const daysSince = lastEngaged\n ? Math.floor(now.diff(lastEngaged, 'days').days)\n : 999;\n\n let tier, engagement_score, action_taken;\n if (daysSince < 30) {\n tier = 'active'; engagement_score = 100; action_taken = 'none';\n } else if (daysSince < 60) {\n tier = 'moderate_decay'; engagement_score = 60; action_taken = 'log';\n } else if (daysSince < 90) {\n tier = 'high_decay'; engagement_score = 25; action_taken = 'log';\n } else {\n tier = 'critical'; engagement_score = 0; action_taken = 'suppress';\n }\n\n return {\n json: {\n profile_id: profile.id,\n email: attrs.email,\n days_since_active: daysSince,\n tier,\n engagement_score,\n action_taken,\n run_id: runId\n }\n };\n});\n"
},
"typeVersion": 2
},
{
"id": "82a40c05-1635-4856-bce5-5c35dc3ceca1",
"name": "Log Profiles to DB",
"type": "n8n-nodes-base.postgres",
"position": [
608,
48
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "klaviyo_decay_log",
"cachedResultName": "klaviyo_decay_log"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"options": {}
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "d6d23b5f-a68a-40c0-9157-3ea6e6769913",
"name": "Build Run Summary",
"type": "n8n-nodes-base.code",
"position": [
544,
400
],
"parameters": {
"jsCode": "const items = $input.all();\nlet active = 0, moderate = 0, high = 0, critical = 0;\n\nfor (const item of items) {\n const tier = item.json.tier;\n if (tier === 'active') active++;\n else if (tier === 'moderate_decay') moderate++;\n else if (tier === 'high_decay') high++;\n else if (tier === 'critical') critical++;\n}\n\n// run_id flows through from Score Profiles via item data \u00e2 no cross-node reference needed\nconst runId = items[0]?.json?.run_id || DateTime.now().toFormat('yyyyMMdd-HHmmss');\nconst runStart = DateTime.now().toISO();\n\nreturn [{\n json: {\n run_id: runId,\n run_start: runStart,\n run_end: DateTime.now().toISO(),\n total_profiles: items.length,\n active_count: active,\n moderate_count: moderate,\n high_count: high,\n critical_count: critical,\n suppressed_count: critical,\n status: 'success'\n }\n}];\n"
},
"typeVersion": 2
},
{
"id": "16a4c769-ec52-4d9b-83a9-159aa13fae8c",
"name": "Insert Run Summary",
"type": "n8n-nodes-base.postgres",
"position": [
768,
400
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "klaviyo_run_summary",
"cachedResultName": "klaviyo_run_summary"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"options": {}
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "dab7f2d2-fd60-4805-9894-d8ac3c3cb5f8",
"name": "Build Email HTML",
"type": "n8n-nodes-base.code",
"position": [
992,
400
],
"parameters": {
"jsCode": "const d = $input.first().json;\nconst date = DateTime.now().toFormat('MMMM dd, yyyy');\n\nconst row = (label, count, action, color) =>\n `\n <tr>\n <td style=\"padding:14px 16px;font-size:14px;color:#333;\">${label}</td>\n <td align=\"right\" style=\"padding:14px 16px;font-size:14px;font-weight:600;color:#111;\">\n ${count}\n </td>\n <td style=\"padding:14px 16px;font-size:13px;\">\n <span style=\"\n padding:6px 10px;\n border-radius:6px;\n background:${color.bg};\n color:${color.text};\n font-weight:500;\n \">\n ${action}\n </span>\n </td>\n </tr>\n`;\n\nconst html = `\n<div style=\"background:#f4f6f8;padding:40px 0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;\">\n \n <div style=\"max-width:600px;margin:0 auto;background:#ffffff;border-radius:12px;overflow:hidden;box-shadow:0 8px 24px rgba(0,0,0,0.06);\">\n \n <!-- Header -->\n <div style=\"padding:24px 28px;background:linear-gradient(135deg,#4f46e5,#7c3aed);color:#fff;\">\n <h2 style=\"margin:0;font-size:20px;font-weight:600;\">\n \u00f0 Klaviyo Decay Report\n </h2>\n <p style=\"margin:6px 0 0;font-size:13px;opacity:0.9;\">\n ${date}\n </p>\n </div>\n\n <!-- Summary -->\n <div style=\"padding:20px 28px;border-bottom:1px solid #eee;\">\n <p style=\"margin:0;font-size:14px;color:#555;\">\n Here\u00e2s your latest engagement decay breakdown. Critical profiles have been automatically suppressed to maintain deliverability.\n </p>\n </div>\n\n <!-- Table -->\n <table style=\"width:100%;border-collapse:collapse;\">\n <thead>\n <tr style=\"background:#fafafa;text-transform:uppercase;font-size:11px;color:#888;letter-spacing:0.05em;\">\n <th align=\"left\" style=\"padding:12px 16px;\">Tier</th>\n <th align=\"right\" style=\"padding:12px 16px;\">Profiles</th>\n <th align=\"left\" style=\"padding:12px 16px;\">Status</th>\n </tr>\n </thead>\n <tbody>\n ${row('Active (<30 days)', d.active_count, 'Healthy', {\n bg:'#ecfdf5', text:'#059669'\n })}\n \n ${row('Moderate Decay (30\u00e260 days)', d.moderate_count, 'Monitor', {\n bg:'#fffbeb', text:'#d97706'\n })}\n \n ${row('High Decay (60\u00e290 days)', d.high_count, 'At Risk', {\n bg:'#fff7ed', text:'#ea580c'\n })}\n \n ${row('<strong>Critical (90+ days)</strong>', `<strong>${d.critical_count}</strong>`, 'Suppressed', {\n bg:'#fef2f2', text:'#dc2626'\n })}\n \n <tr style=\"border-top:2px solid #eee;background:#fafafa;\">\n <td style=\"padding:14px 16px;font-weight:600;\">Total</td>\n <td align=\"right\" style=\"padding:14px 16px;font-weight:700;\">\n ${d.total_profiles}\n </td>\n <td></td>\n </tr>\n </tbody>\n </table>\n\n <!-- Footer -->\n <div style=\"padding:20px 28px;font-size:12px;color:#777;border-top:1px solid #eee;\">\n <p style=\"margin:0 0 8px;\">\n <strong>Run ID:</strong> ${d.run_id}\n </p>\n <p style=\"margin:0 0 8px;\">\n <strong>Started:</strong> ${d.run_start}\n </p>\n <p style=\"margin:0;\">\n <strong>Completed:</strong> ${d.run_end}\n </p>\n </div>\n\n </div>\n\n <!-- Bottom note -->\n <div style=\"max-width:600px;margin:12px auto 0;text-align:center;font-size:11px;color:#aaa;\">\n Automated report \u00e2\u00a2 Deliverability Protection System\n </div>\n\n</div>\n`;\n\nreturn [{\n json: {\n html_report: html,\n email_subject: `\u00f0 Klaviyo Decay Report \u00e2 ${date} | ${d.critical_count} suppressed`\n }\n}];"
},
"typeVersion": 2
},
{
"id": "0f061f5f-9db7-4be1-a6e6-1e8f71d8c880",
"name": "Is Critical?",
"type": "n8n-nodes-base.if",
"position": [
544,
592
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "c1",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.tier }}",
"rightValue": "critical"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "c27dff82-61d6-4781-8936-d8f3402105c1",
"name": "Suppress Critical in Batches",
"type": "n8n-nodes-base.code",
"position": [
800,
576
],
"parameters": {
"jsCode": "const criticalProfiles = $input.all();\nif (criticalProfiles.length === 0) {\n return [{ json: { profiles_suppressed: 0, status: 'no_critical_profiles' } }];\n}\n\nconst batchSize = 100;\nconst apiKey = $env.KLAVIYO_API_KEY;\nconst results = [];\nlet totalSuppressed = 0;\n\nfor (let i = 0; i < criticalProfiles.length; i += batchSize) {\n const batch = criticalProfiles.slice(i, i + batchSize);\n const profilesData = batch.map(p => ({\n type: 'profile',\n attributes: { email: p.json.email }\n }));\n\n try {\n await $helpers.httpRequest({\n method: 'POST',\n url: 'https://a.klaviyo.com/api/profile-suppression-bulk-create-jobs/',\n headers: {\n 'Authorization': 'Klaviyo-API-Key ' + apiKey,\n 'revision': '2024-10-15',\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n data: {\n type: 'profile-suppression-bulk-create-job',\n attributes: { profiles: { data: profilesData } }\n }\n })\n });\n totalSuppressed += batch.length;\n } catch (error) {\n results.push({\n json: { batch: Math.floor(i / batchSize) + 1, error: error.message, status: 'error' }\n });\n }\n}\n\nreturn results.length === 0\n ? [{ json: { profiles_suppressed: totalSuppressed, status: 'success' } }]\n : results;\n"
},
"typeVersion": 2
},
{
"id": "3aede6fa-a3cf-4efa-8e71-5e961d2b07ac",
"name": "Error Trigger",
"type": "n8n-nodes-base.errorTrigger",
"position": [
-576,
816
],
"parameters": {},
"typeVersion": 1
},
{
"id": "fa1c848b-f4a9-4485-a279-d9605d9bdad7",
"name": "Prepare Error Data",
"type": "n8n-nodes-base.code",
"position": [
-352,
816
],
"parameters": {
"jsCode": "const err = $json.execution?.error || {};\nconst init = (() => { try { return $('Set: Initialize Run').first().json; } catch(e) { return {}; } })();\n\nreturn [{\n json: {\n run_id: init.run_id || ('err-' + DateTime.now().toMillis()),\n run_start: init.run_start || null,\n run_end: DateTime.now().toISO(),\n total_profiles: 0,\n active_count: 0,\n moderate_count: 0,\n high_count: 0,\n critical_count: 0,\n suppressed_count: 0,\n status: 'failed',\n error_message: err.message || $json.error || 'Unknown error'\n }\n}];\n"
},
"typeVersion": 2
},
{
"id": "99f6f951-a13e-4dc6-aaa6-229aeaac8ade",
"name": "Log Error to DB",
"type": "n8n-nodes-base.postgres",
"position": [
-128,
816
],
"parameters": {
"table": "klaviyo_run_summary",
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"options": {}
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "354b9649-e08e-49d2-9de8-f233ad810ce1",
"name": "Send Error Alert",
"type": "n8n-nodes-base.gmail",
"position": [
96,
816
],
"parameters": {
"sendTo": "your@email.com",
"message": "={{ '<h3>Workflow Error</h3><p><b>Error:</b> ' + ($json.error_message || 'Unknown') + '</p><p><b>Time:</b> ' + DateTime.now().toISO() + '</p>' }}",
"options": {},
"subject": "={{ '[ERROR] Klaviyo Decay Detection Failed \u00e2 ' + $now.toFormat('yyyy-MM-dd') }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "a4f79a36-33a8-4b68-9b33-b707952e4bc0",
"name": "Send a message",
"type": "n8n-nodes-base.gmail",
"position": [
1216,
400
],
"parameters": {
"sendTo": "user@example.com",
"message": "={{ $json.html_report }}",
"options": {},
"subject": "={{ $json.email_subject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"callerPolicy": "workflowsFromSameOwner",
"availableInMCP": false,
"executionOrder": "v1",
"saveManualExecutions": true
},
"versionId": "e08558ce-fdae-4aed-a183-a62975e15bbf",
"connections": {
"Is Critical?": {
"main": [
[
{
"node": "Suppress Critical in Batches",
"type": "main",
"index": 0
}
]
]
},
"Error Trigger": {
"main": [
[
{
"node": "Prepare Error Data",
"type": "main",
"index": 0
}
]
]
},
"Score Profiles": {
"main": [
[
{
"node": "Log Profiles to DB",
"type": "main",
"index": 0
},
{
"node": "Build Run Summary",
"type": "main",
"index": 0
},
{
"node": "Is Critical?",
"type": "main",
"index": 0
}
]
]
},
"Log Error to DB": {
"main": [
[
{
"node": "Send Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Build Email HTML": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
},
"Get All Profiles": {
"main": [
[
{
"node": "Extract Profile Items",
"type": "main",
"index": 0
}
]
]
},
"Build Run Summary": {
"main": [
[
{
"node": "Insert Run Summary",
"type": "main",
"index": 0
}
]
]
},
"Insert Run Summary": {
"main": [
[
{
"node": "Build Email HTML",
"type": "main",
"index": 0
}
]
]
},
"Prepare Error Data": {
"main": [
[
{
"node": "Log Error to DB",
"type": "main",
"index": 0
}
]
]
},
"Schedule: Daily 2AM": {
"main": [
[
{
"node": "Set: Initialize Run",
"type": "main",
"index": 0
}
]
]
},
"Set: Initialize Run": {
"main": [
[
{
"node": "Get All Profiles",
"type": "main",
"index": 0
}
]
]
},
"Extract Profile Items": {
"main": [
[
{
"node": "Score Profiles",
"type": "main",
"index": 0
}
]
]
}
}
}
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.
gmailOAuth2httpHeaderAuthpostgres
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Klaviyo List Decay Detection
Source: https://n8n.io/workflows/15359/ — 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.
Behavioral analytics: Real-time analysis of product usage and engagement signals Churn prediction: Predictive model identifying at-risk customers 15 days before Smart upselling: Personalized recommend
This workflow is an automated invoice payment tracking and reminder system for the Polish accounting service iFirma.pl. It monitors unpaid and overdue invoices, then automatically sends escalating rem
Automatically extract structured information from emails using AI-powered document analysis. This workflow processes emails from specified domains, classifies them by type, and extracts structured dat
Keep your IT operations moving, every action email becomes a tracked task, and every security alert lands where it belongs, automatically.
What This Flow Does