n8n for MarTech SaaS Vendors: 5 Automations for CCPA, GDPR Consent, CAN-SPAM, CASL, and ePrivacy Compliance
If you build or sell email marketing software, consent management platforms (CMPs), CDPs, ad-tech DSPs, or any MarTech SaaS that touches user data and commercial messaging, you're an actor in a dense global compliance web: CCPA/CPRA, GDPR Art.7, CAN-SPAM, CASL, ePrivacy Directive, IAB TCF 2.2, TCPA, and a growing patchwork of US state privacy laws.
Your customers rely on your platform to prove they have valid consent — and if your API goes down, their consent receipts gap. If your opt-out pipeline breaks, their customers' legal rights are impaired. Your uptime is their compliance.
These five n8n workflow JSONs operationalize that obligation. Drop them into your self-hosted n8n instance and wire to your Postgres database and Slack.
Why self-hosted n8n? Your consent receipts, email suppression lists, and behavioral data are your customers' most sensitive personal information. Routing them through Zapier or Make.com adds an additional GDPR Art.28 data processor to your customers' data flow — one they'll need to disclose in every privacy policy and DPA. Self-hosted n8n eliminates that exposure.
Workflow 1: Email Marketing & Consent Compliance Onboarding Drip
Segment customers by tier (ENTERPRISE_BRAND / MID_MARKET_BRAND / SMB_ECOMMERCE / AGENCY / PUBLISHER) and flag each account with its actual compliance obligations on signup:
-
CPRA_SENSITIVE_PI— CPRA §1798.135 sensitive PI opt-out required (precise geolocation, racial origin, health/sex life) -
GDPR_CONSENT_REQUIRED— GDPR Art.7 consent standard: freely given, specific, informed, unambiguous -
CASL_APPLICABLE— CASL §6 express consent records 3 years, unsubscribe ≤10 business days -
CAN_SPAM_COMMERCIAL— CAN-SPAM 15 USC §7704: opt-out ≤10 business days, FTC enforcement $50,120/email -
CCPA_SALE_SHARING— CCPA §1798.120(a): right to opt-out of sale/sharing of personal information -
EPRIVACY_COOKIE_BANNER— ePrivacy Directive Art.5(3): prior informed consent for non-essential cookies -
TCPA_SMS_APPLICABLE— TCPA 47 USC §227: express written consent for marketing SMS
Day 0: compliance overview email with active flags listed.
Day 3: consent receipt checklist + data flow map, with specific regulatory citations per active flag.
Day 7: CAN-SPAM/CASL subject line guide + suppression list management — marks onboarding complete.
{
"name": "Email Marketing & Consent Onboarding Drip",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"minutesInterval": 1
}
]
}
},
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
240,
300
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT * FROM martech_customers WHERE onboarding_status = 'active' AND next_email_date <= NOW()"
},
"name": "Get Active Customers",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
460,
300
]
},
{
"parameters": {
"jsCode": "const items = [];\nfor (const customer of $input.all()) {\n const c = customer.json;\n const flags = {\n CPRA_SENSITIVE_PI: c.cpra_sensitive_pi,\n GDPR_CONSENT_REQUIRED: c.gdpr_consent_required,\n CASL_APPLICABLE: c.casl_applicable,\n CAN_SPAM_COMMERCIAL: c.can_spam_commercial,\n CCPA_SALE_SHARING: c.ccpa_sale_sharing,\n EPRIVACY_COOKIE_BANNER: c.eprivacy_cookie_banner,\n TCPA_SMS_APPLICABLE: c.tcpa_sms_applicable\n };\n const tier = c.customer_tier;\n const day = c.onboarding_day;\n let subject = '';\n let body = '';\n if (day === 0) {\n subject = `[FlowKit] Welcome ${c.company_name} \u2014 Your Consent Compliance Setup Guide`;\n body = `Welcome to FlowKit!\\n\\nYour compliance flags: ${Object.entries(flags).filter(([k,v])=>v).map(([k])=>k).join(', ')||'Standard'}\\n\\nDay 0: Review your data flow map and consent receipt requirements.`;\n } else if (day === 3) {\n subject = `[FlowKit] Day 3: Consent Receipt Checklist + Data Flow Map for ${c.company_name}`;\n body = `Day 3 check-in:\\n\\n${flags.GDPR_CONSENT_REQUIRED?'GDPR Art.7: Consent must be freely given, specific, informed, unambiguous. Withdrawal as easy as giving.\\n':''}${flags.CAN_SPAM_COMMERCIAL?'CAN-SPAM 15 USC \u00a77704: Opt-out honored within 10 business days. FTC enforcement: $50,120/email.\\n':''}${flags.CASL_APPLICABLE?'CASL \u00a76: Express consent records 3 years. Unsubscribe honored within 10 business days. CRTC max $10M/violation.\\n':''}${flags.EPRIVACY_COOKIE_BANNER?'ePrivacy Directive Art.5(3): Prior informed consent required for non-essential cookies (not just GDPR LIA).\\n':''}\\nSend us your consent management platform (CMP) endpoint for health monitoring setup.`;\n } else if (day === 7) {\n subject = `[FlowKit] Day 7: CAN-SPAM/CASL Subject Line Guide + Suppression List Management`;\n body = `Day 7 onboarding complete:\\n\\n${flags.CCPA_SALE_SHARING?'CCPA \u00a71798.120(a): Honor opt-out of sale/sharing. Pipeline alert if opt-out system DOWN.\\n':''}${flags.CPRA_SENSITIVE_PI?'CPRA \u00a71798.135: Sensitive PI opt-out (precise geolocation, racial origin, health/sex life) \u2014 separate consent flow required.\\n':''}\\nYour n8n compliance dashboard is live. Weekly KPI report starts next Monday.';\n }\n if (subject) {\n items.push({ json: { ...c, email_subject: subject, email_body: body, flags } });\n }\n}\nreturn items;"
},
"name": "Build Email by Day + Flags",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
680,
300
]
},
{
"parameters": {
"fromEmail": "compliance@flowkit.io",
"toEmail": "={{ $json.contact_email }}",
"subject": "={{ $json.email_subject }}",
"text": "={{ $json.email_body }}"
},
"name": "Send Onboarding Email",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
900,
300
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "UPDATE martech_customers SET onboarding_day = onboarding_day + 1, next_email_date = NOW() + INTERVAL '3 days', last_email_sent = NOW() WHERE id = '{{ $json.id }}'"
},
"name": "Advance Onboarding Day",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
1120,
300
]
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "Get Active Customers",
"type": "main",
"index": 0
}
]
]
},
"Get Active Customers": {
"main": [
[
{
"node": "Build Email by Day + Flags",
"type": "main",
"index": 0
}
]
]
},
"Build Email by Day + Flags": {
"main": [
[
{
"node": "Send Onboarding Email",
"type": "main",
"index": 0
}
]
]
},
"Send Onboarding Email": {
"main": [
[
{
"node": "Advance Onboarding Day",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 2: Consent Platform & CMP Health Monitor
Polls 6 CMP infrastructure endpoints every 3 minutes. Each endpoint carries a regulatory annotation explaining the specific compliance risk if it goes DOWN:
| Endpoint | Regulatory Risk |
|---|---|
| Consent API | GDPR Art.7 consent logging gap |
| Cookie Banner CDN | ePrivacy Directive Art.5(3) unlawful processing risk |
| Geo Routing Service | Wrong consent UI served to EU/CA users |
| Consent Receipt DB | CASL 3-year record retention at risk |
| Preference Center UI | CCPA §1798.120(a) + CPRA §1798.135 opt-out impaired |
| IAB TCF Vendor List | Stale TCF consent string — CNIL/ICO enforcement risk |
On any DOWN: Slack alert to #consent-platform-ops + Gmail to Privacy Lead.
CNIL enforcement context: CNIL fined Google €150M and Facebook €60M in January 2022 for cookie consent interfaces that made refusing harder than accepting — both consent mechanisms were intact, but the UX failed Art.5(3). A DOWN banner is a harder violation than a difficult banner.
{
"name": "Consent Platform & CMP Health Monitor",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 3
}
]
}
},
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
240,
300
]
},
{
"parameters": {
"jsCode": "return [\n { json: { name: 'Consent API Endpoint', url: 'https://consent-api.yourplatform.io/health', regulatory_note: 'GDPR Art.7 consent receipts \u2014 DOWN = consent logging gap, Art.7(1) compliance risk', critical: true } },\n { json: { name: 'Cookie Banner CDN', url: 'https://cdn.yourplatform.io/banner/status', regulatory_note: 'ePrivacy Directive Art.5(3): prior consent required for non-essential cookies \u2014 banner DOWN = unlawful processing risk', critical: true } },\n { json: { name: 'Geo Routing Service', url: 'https://geo.yourplatform.io/health', regulatory_note: 'GDPR/CPRA routing: EU visitors must hit GDPR flow, CA residents CCPA flow \u2014 DOWN = wrong consent UI served', critical: true } },\n { json: { name: 'Consent Receipt DB', url: 'https://receipts.yourplatform.io/health', regulatory_note: 'CASL \u00a76: express consent records must be retained 3 years \u2014 DB DOWN = records at risk', critical: false } },\n { json: { name: 'Preference Center UI', url: 'https://preferences.yourplatform.io/health', regulatory_note: 'CCPA \u00a71798.120(a) opt-out + CPRA \u00a71798.135 sensitive PI opt-out \u2014 DOWN = opt-out right impaired', critical: true } },\n { json: { name: 'IAB TCF Vendor List', url: 'https://vendor-list.consensu.org/v3/vendor-list.json', regulatory_note: 'IAB TCF 2.2: vendor list must be current \u2014 stale list = invalid TCF consent string, CNIL/ICO enforcement risk', critical: false } }\n];"
},
"name": "Define CMP Endpoints",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
300
]
},
{
"parameters": {
"url": "={{ $json.url }}",
"options": {
"timeout": 10000,
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"name": "Check Endpoint",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
680,
300
],
"continueOnFail": true
},
{
"parameters": {
"jsCode": "const result = $input.first().json;\nconst endpoint = $('Define CMP Endpoints').first().json;\nconst isDown = result.error || result.statusCode >= 400;\nif (!isDown) return [];\nreturn [{ json: {\n endpoint_name: endpoint.name,\n url: endpoint.url,\n regulatory_note: endpoint.regulatory_note,\n critical: endpoint.critical,\n status: 'DOWN',\n ts: new Date().toISOString()\n}}];"
},
"name": "Filter Failures",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
900,
300
]
},
{
"parameters": {
"authentication": "oAuth2",
"resource": "message",
"operation": "post",
"channel": "#consent-platform-ops",
"text": "=:rotating_light: *CMP HEALTH ALERT* :rotating_light:\\n\\n*Endpoint DOWN:* {{ $json.endpoint_name }}\\n*URL:* {{ $json.url }}\\n*Regulatory Risk:* {{ $json.regulatory_note }}\\n*Critical:* {{ $json.critical ? 'YES \u2014 immediate action required' : 'Monitor' }}\\n*Time:* {{ $json.ts }}"
},
"name": "Alert Slack",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.2,
"position": [
1120,
240
]
},
{
"parameters": {
"fromEmail": "alerts@flowkit.io",
"toEmail": "cmp-lead@yourplatform.io",
"subject": "=[CONSENT PLATFORM DOWN] {{ $json.endpoint_name }} \u2014 {{ $json.regulatory_note.substring(0,60) }}...",
"text": "=CMP Health Alert\\n\\nEndpoint: {{ $json.endpoint_name }}\\nURL: {{ $json.url }}\\nStatus: DOWN\\nRegulatory Risk: {{ $json.regulatory_note }}\\nTimestamp: {{ $json.ts }}\\n\\nImmediate investigation required."
},
"name": "Email Privacy Lead",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
1120,
380
]
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "Define CMP Endpoints",
"type": "main",
"index": 0
}
]
]
},
"Define CMP Endpoints": {
"main": [
[
{
"node": "Check Endpoint",
"type": "main",
"index": 0
}
]
]
},
"Check Endpoint": {
"main": [
[
{
"node": "Filter Failures",
"type": "main",
"index": 0
}
]
]
},
"Filter Failures": {
"main": [
[
{
"node": "Alert Slack",
"type": "main",
"index": 0
},
{
"node": "Email Privacy Lead",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 3: Global Consent & Marketing Law Deadline Tracker
Weekday 7AM check across 12 deadline types, with severity classification (OVERDUE / CRITICAL ≤7d / URGENT ≤21d / WARNING ≤45d) and deduplication via alert_sent_date:
-
GDPR_ART7_CONSENT_AUDIT— consent freely given, specific, informed, unambiguous -
CCPA_PRIVACY_POLICY_ANNUAL_UPDATE— §1798.135 required annual update -
CPRA_SENSITIVE_PI_OPT_OUT_REVIEW— sensitive PI opt-out mechanism review -
CAN_SPAM_SUPPRESSION_LIST_REVIEW— 15 USC §7704 suppression integrity check -
CASL_CONSENT_RECORD_AUDIT— §6 3-year retention compliance -
EPRIVACY_COOKIE_BANNER_ANNUAL_REVIEW— Art.5(3) banner UX/language review -
IAB_TCF_VENDOR_LIST_UPDATE— TCF 2.2 vendor list currency check -
GDPR_DPA_ANNUAL_REVIEW— Art.28 DPA review for all sub-processors -
CCPA_CPRA_DATA_MINIMIZATION_AUDIT— annual data minimization compliance -
TCPA_REVOCATION_PROCEDURE_REVIEW— 47 USC §227 revocation procedure -
STATE_PRIVACY_LAW_NEW_LAW_REVIEW— TX/MT/OR/NH horizon scan -
SOC2_TYPE2_RENEWAL— annual SOC 2 renewal
{
"name": "Global Consent & Marketing Law Deadline Tracker",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 7 * * 1-5"
}
]
}
},
"name": "Weekday 7AM",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
240,
300
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT * FROM consent_compliance_deadlines WHERE completed = false ORDER BY due_date ASC"
},
"name": "Get Deadlines",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
460,
300
]
},
{
"parameters": {
"jsCode": "const items = [];\nconst now = new Date();\nconst TYPES = {\n GDPR_ART7_CONSENT_AUDIT: 'GDPR Art.7 Consent Audit \u2014 consent freely given, specific, informed, unambiguous',\n CCPA_PRIVACY_POLICY_ANNUAL_UPDATE: 'CCPA \u00a71798.135 Privacy Policy Annual Update',\n CPRA_SENSITIVE_PI_OPT_OUT_REVIEW: 'CPRA \u00a71798.135 Sensitive PI Opt-Out Annual Review',\n CAN_SPAM_SUPPRESSION_LIST_REVIEW: 'CAN-SPAM 15 USC \u00a77704 Suppression List Review',\n CASL_CONSENT_RECORD_AUDIT: 'CASL \u00a76 Consent Record Audit (3-year retention)',\n EPRIVACY_COOKIE_BANNER_ANNUAL_REVIEW: 'ePrivacy Directive Art.5(3) Cookie Banner Annual Review',\n IAB_TCF_VENDOR_LIST_UPDATE: 'IAB TCF 2.2 Vendor List Update Check',\n GDPR_DPA_ANNUAL_REVIEW: 'GDPR Art.28 DPA Annual Review (all sub-processors)',\n CCPA_CPRA_DATA_MINIMIZATION_AUDIT: 'CCPA/CPRA Data Minimization Annual Audit',\n TCPA_REVOCATION_PROCEDURE_REVIEW: 'TCPA 47 USC \u00a7227 Revocation Procedure Annual Review',\n STATE_PRIVACY_LAW_NEW_LAW_REVIEW: 'State Privacy Law New-Law Horizon Scan (TX/MT/OR/etc.)',\n SOC2_TYPE2_RENEWAL: 'SOC 2 Type II Annual Renewal'\n};\nfor (const item of $input.all()) {\n const d = item.json;\n const due = new Date(d.due_date);\n const daysLeft = Math.round((due - now) / 86400000);\n let severity = 'NOTICE';\n if (daysLeft < 0) severity = 'OVERDUE';\n else if (daysLeft <= 7) severity = 'CRITICAL';\n else if (daysLeft <= 21) severity = 'URGENT';\n else if (daysLeft <= 45) severity = 'WARNING';\n if (['OVERDUE','CRITICAL','URGENT','WARNING'].includes(severity) && !d.alert_sent_date) {\n items.push({ json: { ...d, days_left: daysLeft, severity, type_label: TYPES[d.deadline_type] || d.deadline_type } });\n }\n}\nreturn items;"
},
"name": "Classify Severity",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
680,
300
]
},
{
"parameters": {
"fromEmail": "compliance@flowkit.io",
"toEmail": "privacy@yourplatform.io",
"subject": "=[{{ $json.severity }}] {{ $json.deadline_type }} due {{ $json.due_date }}",
"text": "=Consent & Marketing Law Compliance Deadline Alert\\n\\nDeadline: {{ $json.type_label }}\\nDue: {{ $json.due_date }}\\nDays remaining: {{ $json.days_left }}\\nSeverity: {{ $json.severity }}\\n\\nAction required immediately."
},
"name": "Email Compliance Team",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
900,
300
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "UPDATE consent_compliance_deadlines SET alert_sent_date = NOW() WHERE id = '{{ $json.id }}'"
},
"name": "Mark Alert Sent",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
1120,
300
]
}
],
"connections": {
"Weekday 7AM": {
"main": [
[
{
"node": "Get Deadlines",
"type": "main",
"index": 0
}
]
]
},
"Get Deadlines": {
"main": [
[
{
"node": "Classify Severity",
"type": "main",
"index": 0
}
]
]
},
"Classify Severity": {
"main": [
[
{
"node": "Email Compliance Team",
"type": "main",
"index": 0
}
]
]
},
"Email Compliance Team": {
"main": [
[
{
"node": "Mark Alert Sent",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 4: Global Marketing Consent Incident Pipeline
Webhook-triggered pipeline with 8 consent incident types, each with its regulatory clock pre-wired:
| Incident Type | Regulation | Clock |
|---|---|---|
| GDPR_CONSENT_WITHDRAWAL_MASS_EXERCISE | GDPR Art.17 erasure | 720h (30 days) |
| CCPA_OPT_OUT_SYSTEM_FAILURE | CCPA §1798.120(a) | 1,080h (45 days cure) |
| CASL_UNSUBSCRIBE_MECHANISM_DOWN | CASL CRTC §6(2)(c) | 240h (10 biz days) |
| CAN_SPAM_SUPPRESSION_FAILURE | CAN-SPAM 15 USC §7704(a)(4) | 240h (10 biz days) |
| CPRA_SENSITIVE_PI_EXPOSURE | CPRA §1798.150 | 72h |
| COOKIE_BANNER_BYPASS | ePrivacy Directive Art.5(3) | 48h |
| FTC_CAN_SPAM_COMPLAINT | FTC enforcement | 168h (preserve records) |
| CNIL_GDPR_COMPLAINT_FILED | GDPR Art.83 — max 4% global turnover | 720h (legal review) |
Returns ACK 200 with incident_id and response_deadline. Logs to Postgres consent_incidents for audit trail.
{
"name": "Global Marketing Consent Incident Pipeline",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "consent-incident",
"responseMode": "responseNode"
},
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
300
]
},
{
"parameters": {
"jsCode": "const body = $input.first().json.body;\nconst INCIDENT_CONFIG = {\n GDPR_CONSENT_WITHDRAWAL_MASS_EXERCISE: { severity: 'CRITICAL', clock_hours: 720, regulation: 'GDPR Art.17: erasure within 1 month (30 days) of valid withdrawal request', notify: ['privacy@yourplatform.io','legal@yourplatform.io'] },\n CCPA_OPT_OUT_SYSTEM_FAILURE: { severity: 'CRITICAL', clock_hours: 1080, regulation: 'CCPA \u00a71798.120(a): opt-out right impaired \u2014 cure within 45 days or enforcement exposure', notify: ['privacy@yourplatform.io','cpo@yourplatform.io'] },\n CASL_UNSUBSCRIBE_MECHANISM_DOWN: { severity: 'CRITICAL', clock_hours: 240, regulation: 'CASL CRTC \u00a76(2)(c): unsubscribe must be honored within 10 business days \u2014 DOWN = violation risk', notify: ['privacy@yourplatform.io','legal@yourplatform.io'] },\n CAN_SPAM_SUPPRESSION_FAILURE: { severity: 'HIGH', clock_hours: 240, regulation: 'CAN-SPAM 15 USC \u00a77704(a)(4): opt-out honored within 10 business days \u2014 FTC $50,120/email', notify: ['privacy@yourplatform.io'] },\n CPRA_SENSITIVE_PI_EXPOSURE: { severity: 'CRITICAL', clock_hours: 72, regulation: 'CPRA \u00a71798.150: breach of sensitive PI \u2014 AG notification + CPPA enforcement', notify: ['privacy@yourplatform.io','ciso@yourplatform.io','legal@yourplatform.io'] },\n COOKIE_BANNER_BYPASS: { severity: 'HIGH', clock_hours: 48, regulation: 'ePrivacy Directive Art.5(3): prior consent required \u2014 bypass = unlawful processing \u2014 CNIL enforcement up to \u20ac150M', notify: ['privacy@yourplatform.io','engineering@yourplatform.io'] },\n FTC_CAN_SPAM_COMPLAINT: { severity: 'HIGH', clock_hours: 168, regulation: 'FTC CAN-SPAM enforcement \u2014 retain all records, preserve suppression lists', notify: ['legal@yourplatform.io','privacy@yourplatform.io'] },\n CNIL_GDPR_COMPLAINT_FILED: { severity: 'CRITICAL', clock_hours: 720, regulation: 'CNIL/ICO/DPA complaint \u2014 GDPR Art.83 max fine 4% global turnover \u2014 immediate legal review', notify: ['legal@yourplatform.io','privacy@yourplatform.io','ceo@yourplatform.io'] }\n};\nconst config = INCIDENT_CONFIG[body.incident_type];\nif (!config) throw new Error('Unknown incident type: ' + body.incident_type);\nconst deadline = new Date(Date.now() + config.clock_hours * 3600000).toISOString();\nreturn [{ json: { ...body, ...config, response_deadline: deadline, incident_id: 'MKTG-' + Date.now() } }];"
},
"name": "Classify & Build Incident",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
300
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "INSERT INTO consent_incidents (incident_id, incident_type, severity, regulation, response_deadline, created_at) VALUES ('{{ $json.incident_id }}', '{{ $json.incident_type }}', '{{ $json.severity }}', '{{ $json.regulation }}', '{{ $json.response_deadline }}', NOW())"
},
"name": "Log to Postgres",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
680,
300
]
},
{
"parameters": {
"fromEmail": "incidents@flowkit.io",
"toEmail": "={{ $json.notify.join(',') }}",
"subject": "=[{{ $json.severity }}] CONSENT INCIDENT {{ $json.incident_id }}: {{ $json.incident_type }}",
"text": "=Consent Incident Alert\\n\\nID: {{ $json.incident_id }}\\nType: {{ $json.incident_type }}\\nSeverity: {{ $json.severity }}\\nRegulatory Clock: {{ $json.regulation }}\\nResponse Deadline: {{ $json.response_deadline }}\\n\\nImmediate legal review required."
},
"name": "Email Incident Team",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
900,
300
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ status: 'received', incident_id: $json.incident_id, response_deadline: $json.response_deadline }) }}"
},
"name": "ACK 200",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1120,
300
]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Classify & Build Incident",
"type": "main",
"index": 0
}
]
]
},
"Classify & Build Incident": {
"main": [
[
{
"node": "Log to Postgres",
"type": "main",
"index": 0
}
]
]
},
"Log to Postgres": {
"main": [
[
{
"node": "Email Incident Team",
"type": "main",
"index": 0
}
]
]
},
"Email Incident Team": {
"main": [
[
{
"node": "ACK 200",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 5: Weekly MarTech Compliance KPI Dashboard
Monday 8AM. Queries Postgres for 7 KPIs. Adds subject-line flags when thresholds are breached. Emails CEO + CMO with DPO and CISO BCC.
Automatic subject-line flags:
-
[CONSENT INCIDENT OPEN]— unresolved critical incident -
[CCPA OPT-OUT SYSTEM DOWN]— opt-out mechanism failure this week -
[CASL UNSUBSCRIBE BROKEN]— unsubscribe failure this week -
[REGULATOR COMPLAINT FILED]— CNIL/FTC/CRTC complaint -
[COOKIE BANNER BYPASS]— banner bypass events this week
{
"name": "Weekly MarTech Compliance KPI Dashboard",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1"
}
]
}
},
"name": "Monday 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
240,
300
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT\n COUNT(CASE WHEN consent_gap_detected AND created_at > NOW()-INTERVAL '7 days' THEN 1 END) AS new_consent_gaps,\n COUNT(CASE WHEN incident_type = 'CCPA_OPT_OUT_SYSTEM_FAILURE' AND created_at > NOW()-INTERVAL '7 days' THEN 1 END) AS opt_out_failures,\n COUNT(CASE WHEN incident_type = 'CASL_UNSUBSCRIBE_MECHANISM_DOWN' AND created_at > NOW()-INTERVAL '7 days' THEN 1 END) AS unsubscribe_failures,\n COUNT(CASE WHEN incident_type LIKE 'CNIL_%' OR incident_type LIKE 'FTC_%' AND created_at > NOW()-INTERVAL '7 days' THEN 1 END) AS regulator_complaints,\n COUNT(CASE WHEN severity = 'CRITICAL' AND resolved_at IS NULL THEN 1 END) AS open_critical_incidents,\n AVG(EXTRACT(EPOCH FROM (resolved_at - created_at))/3600) AS avg_resolution_hrs,\n COUNT(CASE WHEN incident_type = 'COOKIE_BANNER_BYPASS' AND created_at > NOW()-INTERVAL '7 days' THEN 1 END) AS cookie_banner_bypasses\nFROM consent_incidents;"
},
"name": "Query KPIs",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
460,
300
]
},
{
"parameters": {
"jsCode": "const k = $input.first().json;\nconst flags = [\n k.open_critical_incidents > 0 ? '[CONSENT INCIDENT OPEN]' : null,\n k.opt_out_failures > 0 ? '[CCPA OPT-OUT SYSTEM DOWN]' : null,\n k.unsubscribe_failures > 0 ? '[CASL UNSUBSCRIBE BROKEN]' : null,\n k.regulator_complaints > 0 ? '[REGULATOR COMPLAINT FILED]' : null,\n k.cookie_banner_bypasses > 0 ? '[COOKIE BANNER BYPASS]' : null\n].filter(Boolean);\nconst subject = flags.length > 0 ? flags.join(' ') + ' \u2014 MarTech KPI Alert' : 'Weekly MarTech Compliance KPI Report';\nconst html = `<h2>Weekly MarTech Compliance KPI</h2><table border='1' cellpadding='6'><tr><th>Metric</th><th>Value</th></tr><tr><td>New consent gaps (7d)</td><td>${k.new_consent_gaps}</td></tr><tr><td>CCPA opt-out failures (7d)</td><td>${k.opt_out_failures}</td></tr><tr><td>CASL unsubscribe failures (7d)</td><td>${k.unsubscribe_failures}</td></tr><tr><td>Regulator complaints (7d)</td><td>${k.regulator_complaints}</td></tr><tr><td>Open critical incidents</td><td>${k.open_critical_incidents}</td></tr><tr><td>Cookie banner bypasses (7d)</td><td>${k.cookie_banner_bypasses}</td></tr><tr><td>Avg resolution time (hrs)</td><td>${k.avg_resolution_hrs?.toFixed(1)||'N/A'}</td></tr></table>`;\nreturn [{ json: { subject, html, ...k } }];"
},
"name": "Build KPI Report",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
680,
300
]
},
{
"parameters": {
"fromEmail": "kpi@flowkit.io",
"toEmail": "ceo@yourplatform.io",
"subject": "={{ $json.subject }}",
"html": "={{ $json.html }}",
"options": {
"ccEmail": "cmo@yourplatform.io, dpo@yourplatform.io, ciso@yourplatform.io"
}
},
"name": "Email CEO+CMO+DPO+CISO",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2,
"position": [
900,
300
]
}
],
"connections": {
"Monday 8AM": {
"main": [
[
{
"node": "Query KPIs",
"type": "main",
"index": 0
}
]
]
},
"Query KPIs": {
"main": [
[
{
"node": "Build KPI Report",
"type": "main",
"index": 0
}
]
]
},
"Build KPI Report": {
"main": [
[
{
"node": "Email CEO+CMO+DPO+CISO",
"type": "main",
"index": 0
}
]
]
}
}
}
Self-Hosting Table: Why MarTech SaaS Vendors Choose n8n
| Compliance Requirement | Self-Hosted n8n | Cloud iPaaS (Zapier/Make) |
|---|---|---|
| GDPR Art.28 sub-processor inventory | n8n = zero additional processor | Each cloud integration = new Art.28 processor to disclose |
| CASL consent record retention (3yr) | Records stay in your Postgres | Third-party cloud adds data residency risk |
| CCPA service provider agreement | n8n runs on your infra — no new agreement | Cloud vendor = additional service provider agreement required |
| ePrivacy Art.5(3) consent chain | Full audit trail in your stack | Cloud logs = additional chain-of-custody gap |
| FTC CAN-SPAM suppression integrity | Suppression lists never leave your environment | Third-party processing = additional enforcement exposure |
| CNIL cookie audit evidence | Complete local logs | Cloud vendor subpoena complexity |
Get All 5 Workflows + 14 More
These workflows are part of the FlowKit n8n Compliance Templates collection — 14 industry verticals, 5 workflows each, full JSON.
→ FlowKit on Gumroad — individual templates from $12
Drop questions in the comments — happy to adapt any workflow for your specific consent stack.
Top comments (0)