The IAB TCF 2.2 Consent String Is a Live Compliance Boundary in Every Bid Request
Most AdTech SaaS vendors know the IAB Transparency and Consent Framework exists. Fewer have automated the consequences of a stale or invalid TCF consent string flowing through their bid request pipeline.
Under GDPR Article 6(1)(a), behavioral targeting requires valid consent. The TCF 2.2 consent string is the operational record of that consent. If your DSP or SSP forwards a bid request with an invalid string, every downstream behavioral targeting action lacks a lawful basis under GDPR — not just the string validation failure itself. Your automation pipeline's receipt timestamp is when that clock started.
This article covers five production-ready n8n automations for AdTech and MarTech SaaS platforms. All workflow JSON is included. Store link at the end.
The Compliance Landscape for AdTech/MarTech SaaS in 2025
IAB TCF 2.2 and GDPR Article 6 — the consent string as a live document
The IAB TCF 2.2 specification (released April 2023) requires consent management platforms to issue consent strings that are specific to purpose codes 1–10. Purpose 1 (store and/or access information on a device) requires consent; Purpose 3 (create a personalized ads profile) requires consent; Purpose 4 (select personalized ads) requires consent. Bundled consent — one checkbox for all purposes — does not satisfy GDPR's 'specific' requirement under Art.7(2).
Each consent string carries an expiry. TCF 2.2 §8.5 requires CMPs to re-obtain consent after material changes to the purposes disclosed. A consent string that was valid at collection can become invalid if your platform adds a new processing purpose without re-prompting. Your automation pipeline must validate strings at the point of use, not just at the point of collection.
CCPA opt-out of sale and sharing — 15 business days, GPC signal mandatory
California Business and Professions Code §1798.135 (as amended by CPRA) requires businesses to process opt-out requests within 15 business days. Under §1798.135(b)(1), the Global Privacy Control signal must be treated as a valid opt-out of sale and sharing — it cannot be relegated to a secondary process or treated as lower priority than explicit opt-out clicks.
The 'sharing' amendment (effective Jan 1 2023) closed the 'no money changed hands' loophole. Cross-context behavioral advertising using third-party data — without money changing hands — is now 'sharing' under CPRA. Attribution platforms that pass behavioral segments to publisher partners for optimization purposes must handle the GPC signal accordingly.
COPPA 16 CFR §312.5 — the ad server as a primary violator
FTC enforcement history is clear: ad servers and ad networks that knowingly serve targeted ads to children under 13 are primary violators, not secondary actors. The 'knowingly' standard under §312.2 includes constructive knowledge — if the site's subject matter, visual content, music, animated characters, or celebrities popular with children indicate a child-directed audience, the platform cannot claim ignorance.
The FTC's Epic Games settlement ($520M, December 2022) and YouTube settlement ($170M, September 2019) establish that scaled enforcement is real. Your ad delivery pipeline must classify content before serving behavioral ads, not after the ad is delivered.
California AB 2273 Age-Appropriate Design Code — behavioral profiling of minors
AB 2273 (effective January 1, 2025) prohibits online services likely to be accessed by children under 18 from using default settings that enable profiling for behavioral advertising. This is opt-in for minors, not opt-out. Any ad platform serving California users across general consumer contexts must implement under-18 detection and profiling defaults before the ad is served.
FTC Endorsement Guides 16 CFR Part 255 — the 2023 revision expands coverage
The 2023 revision of 16 CFR Part 255 expanded FTC coverage to include: (1) social proof and fake reviews embedded in marketing platforms, (2) AI-generated endorsements and testimonials, (3) virtual influencers whose material connections are not disclosed, and (4) negative option and continuity marketing disguised as influencer-driven organic content. Influencer MarTech platforms that facilitate undisclosed sponsored content face potential secondary liability as platforms.
EU DSA Article 26 — recommender system transparency
DSA Art.26 requires online platforms to disclose to users the 'main parameters' used in recommender systems and to offer at least one option not based on profiling. For AdTech platforms operating recommender infrastructure (programmatic ad placement, personalized content curation), any algorithm change that materially affects the main parameters requires an update to the transparency disclosure. Very Large Online Platforms (>45M monthly EU users) face annual algorithmic accountability reporting under Art.27.
5 Production-Ready n8n Workflows
Workflow 1 — Tier-Segmented Onboarding Drip (7 AdTech Tiers)
Classifies new accounts into 7 tiers: ENTERPRISE_DSP_SSP, DMP_CDP_SAAS, ADSERVER_SAAS, ATTRIBUTION_ANALYTICS_SAAS, EMAIL_MARTECH_SAAS, INFLUENCER_MARTECH_SAAS, ADTECH_STARTUP. Routes each to a compliance-specific email sequence with tier-relevant regulations highlighted.
DSP/SSP tier: IAB TCF 2.2 consent string validation, GDPR Art.6(1)(a) per purpose code, EU DSA Art.26 recommender transparency. DMP/CDP tier: GDPR lawful basis per processing purpose, CCPA cross-context behavioral advertising opt-out, EU ePrivacy Directive cookie consent sequencing. Ad server tier: COPPA §312.5 content classification requirement, CA AB 2273 under-18 profiling default. Attribution tier: CCPA 'sharing' definition post-CPRA, GDPR Art.22 automated profiling right to explanation. Email MarTech: CAN-SPAM 10-day opt-out + CASL express consent + FTC Endorsement Guides 2023. Influencer MarTech: FTC 16 CFR Part 255 material connection disclosure, UK CAP Code §3.41 'Ad' labelling, EU DSA Art.26 commercial communications. Startup: IAB TCF 2.2 string requirement, CCPA §1798.135 GPC signal, EU ePrivacy cookie consent.
{
"name": "AdTech Tier-Segmented Onboarding Drip \u2014 IAB TCF / GDPR / CCPA",
"nodes": [
{
"id": "1",
"name": "New AdTech Account Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
0,
0
],
"parameters": {
"path": "adtech-signup",
"responseMode": "immediately",
"httpMethod": "POST"
}
},
{
"id": "2",
"name": "Classify AdTech Tier",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
200,
0
],
"parameters": {
"jsCode": "const b = $input.first().json.body || $input.first().json;\nconst tier = b.tier || 'ADTECH_STARTUP';\nconst flags = b.compliance_flags || [];\nconst hasEU = flags.includes('EU_GDPR_BEHAVIORAL_TARGETING') || b.eu_users === true;\nconst hasCAUsers = flags.includes('CCPA_OPT_OUT_REQUIRED') || b.ca_users === true;\nconst hasChildren = flags.includes('COPPA_UNDER_13') || b.children_audience === true;\nconst hasInfluencer = tier === 'INFLUENCER_MARTECH_SAAS';\nconst tcfRequired = flags.includes('IAB_TCF_22_PUBLISHER') || tier === 'ENTERPRISE_DSP_SSP';\n\nreturn [{\n json: {\n ...b,\n tier,\n has_eu_users: hasEU,\n has_ca_users: hasCAUsers,\n has_children: hasChildren,\n tcf_required: tcfRequired,\n influencer_platform: hasInfluencer,\n onboarding_track: tier\n }\n}];"
}
},
{
"id": "3",
"name": "Route by Tier",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
400,
0
],
"parameters": {
"mode": "rules",
"rules": {
"values": [
{
"conditions": {
"options": {
"leftValue": "={{ $json.tier }}",
"operation": "equal",
"rightValue": "ENTERPRISE_DSP_SSP"
}
}
},
{
"conditions": {
"options": {
"leftValue": "={{ $json.tier }}",
"operation": "equal",
"rightValue": "DMP_CDP_SAAS"
}
}
},
{
"conditions": {
"options": {
"leftValue": "={{ $json.tier }}",
"operation": "equal",
"rightValue": "ADSERVER_SAAS"
}
}
},
{
"conditions": {
"options": {
"leftValue": "={{ $json.tier }}",
"operation": "equal",
"rightValue": "ATTRIBUTION_ANALYTICS_SAAS"
}
}
},
{
"conditions": {
"options": {
"leftValue": "={{ $json.tier }}",
"operation": "equal",
"rightValue": "EMAIL_MARTECH_SAAS"
}
}
},
{
"conditions": {
"options": {
"leftValue": "={{ $json.tier }}",
"operation": "equal",
"rightValue": "INFLUENCER_MARTECH_SAAS"
}
}
},
{
"conditions": {
"options": {
"leftValue": "={{ $json.tier }}",
"operation": "equal",
"rightValue": "ADTECH_STARTUP"
}
}
}
]
}
}
},
{
"id": "4",
"name": "DSP/SSP Email \u2014 TCF 2.2 + GDPR Art.6",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
700,
-600
],
"parameters": {
"operation": "send",
"sendTo": "={{ $json.email }}",
"subject": "Your DSP/SSP compliance checklist \u2014 IAB TCF 2.2 + GDPR Art.6 + EU DSA Art.26",
"message": "<p>Welcome to FlowKit. Your DSP/SSP platform touches three compliance boundaries simultaneously:</p><ul><li><strong>IAB TCF 2.2 consent string validation:</strong> Every bid request must carry a valid TCF consent string. Invalid or stale strings = GDPR Art.6 lawful basis failure for behavioral targeting. The IAB's own enforcement program (TCF 2.2 \u00a78.5) requires real-time string validation before data is passed downstream.</li><li><strong>GDPR Art.6(1)(a) for behavioral profiles:</strong> Consent must be specific, informed, and unambiguous. Pre-ticked boxes, bundled consent, or consent obtained before disclosure of all processing purposes = invalid. Each purpose code (1\u201310) must have individual consent or legitimate interest assessment.</li><li><strong>EU DSA Art.26 recommender system transparency:</strong> If your SSP runs a recommendation algorithm for ad placement, you must disclose the main parameters used. Large platforms (45M+ monthly EU users) face stricter obligations including annual algorithmic accountability reports.</li></ul><p>Your first 3 automations handle TCF string validation, GDPR consent audit, and DSA transparency logging. Setup guide attached.</p>",
"additionalFields": {
"isHtml": true
}
}
},
{
"id": "5",
"name": "DMP/CDP Email \u2014 GDPR Art.6 + CCPA + ePrivacy",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
700,
-400
],
"parameters": {
"operation": "send",
"sendTo": "={{ $json.email }}",
"subject": "DMP/CDP compliance: GDPR Art.6 lawful basis + CCPA opt-out + EU ePrivacy cookie consent",
"message": "<p>Your DMP/CDP ingests behavioral data from multiple sources. Three boundaries require immediate automation:</p><ul><li><strong>GDPR Art.6 lawful basis per processing purpose:</strong> Data onboarding, lookalike modeling, and third-party data enrichment each require a separate lawful basis assessment. A DMP cannot bundle them under a single consent. Each data source and each processing activity needs its own lawful basis record.</li><li><strong>CCPA opt-out of sale/sharing (15-day compliance):</strong> If any behavioral data segment is sold or shared for cross-context behavioral advertising, an opt-out signal (GPC or explicit opt-out) must be honored within 15 business days. \u00a71798.135(b)(1) \u2014 GPC signal from browser must be treated as opt-out request.</li><li><strong>EU ePrivacy Directive cookie/tracking consent:</strong> First-party and third-party cookies for behavioral profiling require prior consent (not opt-out). Pre-consent data collection = ePrivacy violation regardless of GDPR consent.</li></ul>",
"additionalFields": {
"isHtml": true
}
}
},
{
"id": "6",
"name": "AdServer Email \u2014 COPPA CARU + CA AB 2273",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
700,
-200
],
"parameters": {
"operation": "send",
"sendTo": "={{ $json.email }}",
"subject": "Ad server compliance: COPPA \u00a7312.5 + California AB 2273 Age-Appropriate Design Code",
"message": "<p>Your ad server may deliver ads to contexts where children are present. Two frameworks apply immediately:</p><ul><li><strong>COPPA 16 CFR \u00a7312.5:</strong> Ad servers that knowingly serve behavioral or targeted ads to children under 13 are direct violators \u2014 not just the app operator. 'Knowingly' = you have actual knowledge OR the site/app is directed to children (subject matter, music, animated characters, celebrities popular with children). FTC enforcement: Epic Games $520M (2023), YouTube $170M (2019). Your ad delivery pipeline must check content classification before serving targeted ads.</li><li><strong>California AB 2273 Age-Appropriate Design Code (effective Jan 2025):</strong> If your ad server serves California residents under 18, profiling by default is prohibited. Data minimization required for users under 18. Automated profiling for behavioral advertising requires explicit opt-in (not opt-out) for minors.</li></ul>",
"additionalFields": {
"isHtml": true
}
}
},
{
"id": "7",
"name": "Attribution Email \u2014 CCPA + GDPR Art.22",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
700,
0
],
"parameters": {
"operation": "send",
"sendTo": "={{ $json.email }}",
"subject": "Attribution analytics compliance: CCPA cross-context behavioral + GDPR Art.22 automated profiling",
"message": "<p>Attribution analytics platforms create compliance exposure at two points:</p><ul><li><strong>CCPA cross-context behavioral advertising (\u00a71798.140(k)):</strong> Attribution based on behavior across third-party websites or apps = 'sharing' under CPRA even without money exchanged. Must honor opt-out of sharing, not just opt-out of sale. This closes the 'no money changed hands' loophole that many attribution platforms have relied on.</li><li><strong>GDPR Art.22 automated decision-making:</strong> If attribution data is used to make automated decisions with legal or significant effects (ad spend allocation, publisher payment, fraud score), affected parties have a right to explanation and human review. Fully automated decisions = Art.22 obligation without explicit consent or contractual necessity basis.</li></ul>",
"additionalFields": {
"isHtml": true
}
}
},
{
"id": "8",
"name": "Email MarTech Email \u2014 CAN-SPAM + CASL + FTC",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
700,
200
],
"parameters": {
"operation": "send",
"sendTo": "={{ $json.email }}",
"subject": "Email MarTech compliance: CAN-SPAM + CASL + FTC Endorsement Guides 16 CFR Part 255",
"message": "<p>Email marketing platforms face three compliance stacks simultaneously:</p><ul><li><strong>CAN-SPAM + CASL unsubscribe mechanics:</strong> CAN-SPAM requires opt-out processing within 10 business days. CASL requires express consent before sending commercial email to Canadian recipients \u2014 implied consent expires after 2 years unless renewed. Your unsubscribe pipeline must handle both simultaneously.</li><li><strong>FTC Endorsement Guides 16 CFR Part 255 (revised 2023):</strong> Sponsored email content, affiliate links, and influencer-co-branded email campaigns require clear disclosure of material connections. The 2023 revision expanded coverage to social proof, ratings, and testimonials embedded in email marketing.</li><li><strong>GDPR email marketing consent:</strong> Legitimate interest cannot be used for direct marketing in most EU member states. Explicit opt-in required. Soft opt-in (prior business relationship) applies only to own similar products under strict conditions.</li></ul>",
"additionalFields": {
"isHtml": true
}
}
},
{
"id": "9",
"name": "Influencer MarTech Email \u2014 FTC + UK CAP",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
700,
400
],
"parameters": {
"operation": "send",
"sendTo": "={{ $json.email }}",
"subject": "Influencer platform compliance: FTC 16 CFR Part 255 + UK CAP Code + EU DSA Art.26",
"message": "<p>Influencer marketing platforms sit at the intersection of advertising disclosure law and platform liability:</p><ul><li><strong>FTC Endorsement Guides 16 CFR Part 255 (2023 revision):</strong> Material connections (payment, free products, affiliate relationships) must be clearly and conspicuously disclosed. 'Clear and conspicuous' = visible before consumer engagement, not buried in profile bio or #ad tag in a sea of other hashtags. Platforms that facilitate non-disclosed sponsored content face potential FTC enforcement as secondary actors.</li><li><strong>UK CAP Code (ASA) \u00a73.41:</strong> All influencer content with a material relationship must be labelled 'Ad' before any content in the post. 'Partner' or 'gifted' is insufficient \u2014 must say 'Ad'. ASA actively monitors and refers cases to Trading Standards.</li><li><strong>EU DSA Art.26:</strong> Commercial communications to EU users must be identifiable as such in real time. Platforms are required to ensure compliance by commercial account holders. Systemic non-compliance = very large platform (VLP) scrutiny.</li></ul>",
"additionalFields": {
"isHtml": true
}
}
},
{
"id": "10",
"name": "Startup Email \u2014 IAB TCF + CCPA + ePrivacy Starter",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
700,
600
],
"parameters": {
"operation": "send",
"sendTo": "={{ $json.email }}",
"subject": "AdTech startup compliance starter: IAB TCF 2.2 + CCPA opt-out + EU ePrivacy cookie consent",
"message": "<p>Three compliance items to automate before your first campaign:</p><ul><li><strong>IAB TCF 2.2 consent string:</strong> If you integrate with any IAB-compliant DSP or SSP, you need a valid TCF string in every bid request. Invalid strings = bid rejection at the exchange level and potential partner liability. Free CMP integrations exist \u2014 the string generation is not optional.</li><li><strong>CCPA opt-out of sale (15 business days):</strong> If any behavioral data flows to third parties for advertising, the 'Do Not Sell or Share My Personal Information' link and GPC signal must be honored. Even if you are below the threshold for the California Privacy Rights Act, large publisher partners will require CCPA compliance as a contract term.</li><li><strong>EU ePrivacy cookie consent:</strong> Behavioral advertising cookies require prior consent in EU. Analytics-only cookies may use legitimate interest in some member states. Your cookie consent flow must be set up before any EU traffic reaches your ad pipeline.</li></ul>",
"additionalFields": {
"isHtml": true
}
}
}
],
"connections": {
"New AdTech Account Webhook": {
"main": [
[
{
"node": "Classify AdTech Tier",
"type": "main",
"index": 0
}
]
]
},
"Classify AdTech Tier": {
"main": [
[
{
"node": "Route by Tier",
"type": "main",
"index": 0
}
]
]
},
"Route by Tier": {
"main": [
[
{
"node": "DSP/SSP Email \u2014 TCF 2.2 + GDPR Art.6",
"type": "main",
"index": 0
}
],
[
{
"node": "DMP/CDP Email \u2014 GDPR Art.6 + CCPA + ePrivacy",
"type": "main",
"index": 0
}
],
[
{
"node": "AdServer Email \u2014 COPPA CARU + CA AB 2273",
"type": "main",
"index": 0
}
],
[
{
"node": "Attribution Email \u2014 CCPA + GDPR Art.22",
"type": "main",
"index": 0
}
],
[
{
"node": "Email MarTech Email \u2014 CAN-SPAM + CASL + FTC",
"type": "main",
"index": 0
}
],
[
{
"node": "Influencer MarTech Email \u2014 FTC + UK CAP",
"type": "main",
"index": 0
}
],
[
{
"node": "Startup Email \u2014 IAB TCF + CCPA + ePrivacy Starter",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 2 — IAB TCF 2.2 / CCPA / GDPR Consent Deadline Tracker
Daily 6AM UTC cron checks open consent obligation records. Tracks 10 clock types:
- CCPA_OPT_OUT_OF_SALE_15_BIZ — 15 business days from opt-out request receipt §1798.135
- CCPA_DELETION_REQUEST_45D — 45 calendar days from deletion request §1798.130
- IAB_TCF_22_CONSENT_EXPIRY — 13-month maximum consent string validity
- GDPR_ART6_LEGITIMATE_INTEREST_ANNUAL — annual balancing test review for Art.6(1)(f) legitimate interest
- GDPR_DSARS_30D — 30-day DSAR response deadline from receipt
- EU_EPRIVACY_CONSENT_EXPIRY — 6-month re-prompt interval for ePrivacy cookie consent
- CCPA_ANNUAL_POLICY_UPDATE — privacy policy annual update §1798.130(a)(5)
- CA_AB2273_ANNUAL_REVIEW — AB 2273 annual data protection impact assessment
- FTC_ENDORSEMENT_DISCLOSURE_AUDIT — quarterly sponsored content audit 16 CFR Part 255
- GDPR_ART22_CONSENT_ANNUAL — annual review of Art.22 automated profiling consent
Outputs CRITICAL (<24h), WARNING (<72h), WATCH (<168h) alerts to Slack #compliance-alerts.
{
"name": "IAB TCF 2.2 / CCPA / GDPR Consent Compliance Deadline Tracker",
"nodes": [
{
"id": "1",
"name": "Daily Cron 6AM UTC",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
0,
0
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 6 * * *"
}
]
}
}
},
{
"id": "2",
"name": "Load Consent Obligation Queue",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
200,
0
],
"parameters": {
"operation": "executeQuery",
"query": "SELECT account_id, email, tier, obligation_type, trigger_ts, deadline_ts, status, hours_remaining FROM adtech_consent_obligations WHERE status = 'open' AND deadline_ts > NOW() ORDER BY deadline_ts ASC LIMIT 100"
}
},
{
"id": "3",
"name": "Compute Time Windows",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
0
],
"parameters": {
"jsCode": "const items = $input.all();\nconst now = new Date();\n\nconst OBLIGATION_CLOCKS = {\n CCPA_OPT_OUT_OF_SALE_15_BIZ: { hours: 15*8, label: 'CCPA opt-out of sale \u00a71798.135 \u2014 15 business days', severity: 'HIGH' },\n CCPA_DELETION_REQUEST_45D: { hours: 45*24, label: 'CCPA deletion request \u00a71798.130 \u2014 45 calendar days', severity: 'HIGH' },\n IAB_TCF_22_CONSENT_EXPIRY: { hours: 13*30*24, label: 'IAB TCF 2.2 consent string expiry \u2014 13 months max', severity: 'MEDIUM' },\n GDPR_ART6_LEGITIMATE_INTEREST_ANNUAL: { hours: 365*24, label: 'GDPR Art.6(1)(f) legitimate interest annual balancing test review', severity: 'MEDIUM' },\n GDPR_DSARS_30D: { hours: 30*24, label: 'GDPR DSAR \u00a715 response \u2014 30 days', severity: 'HIGH' },\n EU_EPRIVACY_CONSENT_EXPIRY: { hours: 6*30*24, label: 'EU ePrivacy cookie consent \u2014 6 months re-prompt', severity: 'MEDIUM' },\n CCPA_ANNUAL_POLICY_UPDATE: { hours: 365*24, label: 'CCPA privacy policy annual update \u00a71798.130(a)(5)', severity: 'LOW' },\n CA_AB2273_ANNUAL_REVIEW: { hours: 365*24, label: 'CA AB 2273 Age-Appropriate Design Code annual risk assessment', severity: 'MEDIUM' },\n FTC_ENDORSEMENT_DISCLOSURE_AUDIT: { hours: 90*24, label: 'FTC 16 CFR Part 255 sponsored content audit \u2014 quarterly', severity: 'MEDIUM' },\n GDPR_ART22_CONSENT_ANNUAL: { hours: 365*24, label: 'GDPR Art.22 automated profiling consent annual review', severity: 'MEDIUM' }\n};\n\nreturn items.map(item => {\n const d = item.json;\n const deadline = new Date(d.deadline_ts);\n const hoursLeft = (deadline - now) / 3600000;\n const clock = OBLIGATION_CLOCKS[d.obligation_type] || { label: d.obligation_type, severity: 'MEDIUM' };\n let urgency = 'OK';\n if (hoursLeft < 24) urgency = 'CRITICAL';\n else if (hoursLeft < 72) urgency = 'WARNING';\n else if (hoursLeft < 168) urgency = 'WATCH';\n return { json: { ...d, hours_left: Math.round(hoursLeft), urgency, obligation_label: clock.label, severity: clock.severity } };\n}).filter(i => i.json.urgency !== 'OK');"
}
},
{
"id": "4",
"name": "Filter Critical/Warning",
"type": "n8n-nodes-base.filter",
"typeVersion": 2.1,
"position": [
600,
0
],
"parameters": {
"conditions": {
"options": {
"leftValue": "={{ $json.urgency }}",
"operation": "notEqual",
"rightValue": "OK"
}
}
}
},
{
"id": "5",
"name": "Slack #compliance-alerts",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.1,
"position": [
800,
0
],
"parameters": {
"authentication": "accessToken",
"resource": "message",
"operation": "post",
"channel": "#compliance-alerts",
"text": "\ud83d\udd14 AdTech Consent Deadline Alert \u2014 {{ $json.urgency }}\nAccount: {{ $json.account_id }} ({{ $json.tier }})\nObligation: {{ $json.obligation_label }}\nHours remaining: {{ $json.hours_left }}h\nDeadline: {{ $json.deadline_ts }}\nTriggered: {{ $json.trigger_ts }}"
}
}
],
"connections": {
"Daily Cron 6AM UTC": {
"main": [
[
{
"node": "Load Consent Obligation Queue",
"type": "main",
"index": 0
}
]
]
},
"Load Consent Obligation Queue": {
"main": [
[
{
"node": "Compute Time Windows",
"type": "main",
"index": 0
}
]
]
},
"Compute Time Windows": {
"main": [
[
{
"node": "Filter Critical/Warning",
"type": "main",
"index": 0
}
]
]
},
"Filter Critical/Warning": {
"main": [
[
{
"node": "Slack #compliance-alerts",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 3 — AdTech Consent Infrastructure Health Monitor
Every 10 minutes, checks 5 consent infrastructure endpoints:
- iab_tcf_cmp_api — TCF 2.2 CMP down = invalid consent strings in all bid requests = GDPR Art.6 lawful basis failure
- ccpa_opt_out_api — CCPA opt-out pipeline down = 15-day clock running without processing
- gdpr_consent_vault — GDPR consent records inaccessible = Art.7(1) demonstrating consent obligation unmet
- coppa_age_classification_api — Age gate down = behavioral ads potentially reaching under-13 audience
- gpc_signal_processor — GPC processor offline = CCPA §1798.135(b)(1) not being honored
PagerDuty alert on any downtime. A 10-minute outage in the TCF CMP API means 10 minutes of bid requests with unvalidated consent strings.
{
"name": "AdTech Consent Infrastructure Health Monitor",
"nodes": [
{
"id": "1",
"name": "Every 10 Min",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
0,
0
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "*/10 * * * *"
}
]
}
}
},
{
"id": "2",
"name": "Check 5 Endpoints",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
200,
0
],
"parameters": {
"jsCode": "const endpoints = [\n { name: 'iab_tcf_cmp_api', url: process.env.TCF_CMP_API_URL || 'http://localhost:9001/health', risk: 'IAB TCF 2.2 consent string invalid in all bid requests \u2014 GDPR Art.6 lawful basis failure for behavioral targeting' },\n { name: 'ccpa_opt_out_api', url: process.env.CCPA_OPT_OUT_API_URL || 'http://localhost:9002/health', risk: 'CCPA opt-out of sale pipeline down \u2014 15 business day clock running without processing \u00a71798.135' },\n { name: 'gdpr_consent_vault', url: process.env.GDPR_CONSENT_VAULT_URL || 'http://localhost:9003/health', risk: 'GDPR consent records inaccessible \u2014 Art.7(1) demonstrating consent obligation unmet, Art.6 audit gap' },\n { name: 'coppa_age_classification_api', url: process.env.COPPA_AGE_API_URL || 'http://localhost:9004/health', risk: 'COPPA age gate down \u2014 behavioral ads may reach under-13 audience, FTC enforcement risk (Epic $520M precedent)' },\n { name: 'gpc_signal_processor', url: process.env.GPC_PROCESSOR_URL || 'http://localhost:9005/health', risk: 'GPC signal processor offline \u2014 CCPA \u00a71798.135(b)(1) opt-out of sharing not being honored, potential AG complaint' }\n];\nreturn endpoints.map(e => ({ json: e }));"
}
},
{
"id": "3",
"name": "HTTP Health Checks",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
400,
0
],
"parameters": {
"url": "={{ $json.url }}",
"method": "GET",
"options": {
"timeout": 5000,
"response": {
"response": {
"neverError": true
}
}
}
}
},
{
"id": "4",
"name": "Flag Failures",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
600,
0
],
"parameters": {
"jsCode": "const result = $input.first().json;\nconst endpoint = $('Check 5 Endpoints').first().json;\nconst isDown = result.statusCode !== 200;\nif (!isDown) return [];\nreturn [{ json: { endpoint: endpoint.name, risk: endpoint.risk, status: result.statusCode || 'TIMEOUT', ts: new Date().toISOString() } }];"
}
},
{
"id": "5",
"name": "PagerDuty Alert",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
800,
0
],
"parameters": {
"url": "https://events.pagerduty.com/v2/enqueue",
"method": "POST",
"sendBody": true,
"contentType": "json",
"body": {
"routing_key": "={{ $vars.PAGERDUTY_ROUTING_KEY }}",
"event_action": "trigger",
"payload": {
"summary": "AdTech consent infra DOWN: {{ $json.endpoint }} \u2014 {{ $json.risk }}",
"severity": "critical",
"source": "n8n-adtech-monitor",
"timestamp": "={{ $json.ts }}"
}
}
}
}
],
"connections": {
"Every 10 Min": {
"main": [
[
{
"node": "Check 5 Endpoints",
"type": "main",
"index": 0
}
]
]
},
"Check 5 Endpoints": {
"main": [
[
{
"node": "HTTP Health Checks",
"type": "main",
"index": 0
}
]
]
},
"HTTP Health Checks": {
"main": [
[
{
"node": "Flag Failures",
"type": "main",
"index": 0
}
]
]
},
"Flag Failures": {
"main": [
[
{
"node": "PagerDuty Alert",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 4 — AdTech Consent Violation Incident Pipeline
Webhook receives consent events and classifies them into 8 incident types with pre-calculated deadlines:
| Event | Deadline | Action |
|---|---|---|
| IAB_TCF_INVALID_CONSENT_STRING | IMMEDIATE | Suspend bid requests — invalid string = GDPR Art.6 failure |
| CCPA_OPT_OUT_REQUEST_RECEIVED | 15 business days | Honor signal, stop sale/sharing of PI |
| GDPR_CONSENT_WITHDRAWAL | IMMEDIATE | Stop processing based on consent, delete derived profiles |
| COPPA_UNDER13_DETECTED | IMMEDIATE | Remove from behavioral targeting, switch to contextual only |
| FTC_ENDORSEMENT_UNDISCLOSED | IMMEDIATE | Add disclosure or suspend campaign |
| GPC_SIGNAL_RECEIVED | 15 business days | Treat as CCPA opt-out of sharing §1798.135(b)(1) |
| CA_AB2273_PROFILING_MINOR | IMMEDIATE | Remove from profiling pipeline, default to age-appropriate settings |
| GDPR_ART26_RECOMMENDER_CHANGE | 72 hours | Update DSA Art.26 transparency disclosure |
The IMMEDIATE category covers four of the eight incident types. Each IMMEDIATE event has a zero-hour deadline — the clock started when your system received the event, not when a human opened a ticket.
{
"name": "AdTech Consent Violation Incident Pipeline",
"nodes": [
{
"id": "1",
"name": "Consent Event Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
0,
0
],
"parameters": {
"path": "consent-incident",
"responseMode": "immediately",
"httpMethod": "POST"
}
},
{
"id": "2",
"name": "Classify Incident",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
200,
0
],
"parameters": {
"jsCode": "const b = $input.first().json.body || $input.first().json;\nconst type = b.event_type;\nconst accountId = b.account_id;\nconst receivedAt = new Date().toISOString();\n\nconst INCIDENT_MAP = {\n IAB_TCF_INVALID_CONSENT_STRING: { deadline_hours: 1, label: 'IAB TCF 2.2 invalid consent string in bid request', action: 'SUSPEND_BID_REQUESTS \u2014 invalid string = GDPR Art.6 failure for all downstream behavioral targeting', severity: 'CRITICAL' },\n CCPA_OPT_OUT_REQUEST_RECEIVED: { deadline_hours: 15*8, label: 'CCPA opt-out of sale request received \u00a71798.135', action: 'INITIATE_15_BUSINESS_DAY_CLOCK \u2014 honor signal, stop sale/sharing of PI', severity: 'HIGH' },\n GDPR_CONSENT_WITHDRAWAL: { deadline_hours: 0, label: 'GDPR Art.7(3) consent withdrawal', action: 'IMMEDIATE \u2014 stop processing based on consent, delete derived profiles per Art.17', severity: 'CRITICAL' },\n COPPA_UNDER13_DETECTED: { deadline_hours: 0, label: 'COPPA under-13 user detected in behavioral ad pipeline', action: 'IMMEDIATE \u2014 remove from behavioral targeting, delete PI per \u00a7312.10, switch to contextual ads only', severity: 'CRITICAL' },\n FTC_ENDORSEMENT_UNDISCLOSED: { deadline_hours: 0, label: 'FTC 16 CFR Part 255 undisclosed sponsorship detected', action: 'IMMEDIATE \u2014 add disclosure or suspend campaign, log remediation timestamp', severity: 'HIGH' },\n GPC_SIGNAL_RECEIVED: { deadline_hours: 15*8, label: 'GPC opt-out signal received \u00a71798.135(b)(1)', action: 'INITIATE_15_BUSINESS_DAY_CLOCK \u2014 treat as CCPA opt-out of sharing', severity: 'HIGH' },\n CA_AB2273_PROFILING_MINOR: { deadline_hours: 0, label: 'CA AB 2273 automated profiling of user under 18 without opt-in', action: 'IMMEDIATE \u2014 remove from profiling pipeline, switch to age-appropriate default settings', severity: 'CRITICAL' },\n GDPR_ART26_RECOMMENDER_CHANGE: { deadline_hours: 72, label: 'EU DSA Art.26 recommender system parameter change without disclosure update', action: '72H \u2014 update system transparency disclosure per Art.27', severity: 'MEDIUM' }\n};\n\nconst incident = INCIDENT_MAP[type] || { deadline_hours: 24, label: type, action: 'REVIEW_REQUIRED', severity: 'MEDIUM' };\nconst deadlineAt = incident.deadline_hours === 0 ? receivedAt : new Date(Date.now() + incident.deadline_hours * 3600000).toISOString();\n\nreturn [{\n json: {\n account_id: accountId,\n event_type: type,\n incident_label: incident.label,\n action: incident.action,\n severity: incident.severity,\n received_at: receivedAt,\n deadline_at: deadlineAt,\n deadline_hours: incident.deadline_hours\n }\n}];"
}
},
{
"id": "3",
"name": "Slack #adtech-incidents",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.1,
"position": [
400,
-100
],
"parameters": {
"authentication": "accessToken",
"resource": "message",
"operation": "post",
"channel": "#adtech-incidents",
"text": "\ud83d\udea8 AdTech Consent Incident \u2014 {{ $json.severity }}\nType: {{ $json.event_type }}\nAccount: {{ $json.account_id }}\nIncident: {{ $json.incident_label }}\nAction: {{ $json.action }}\nDeadline: {{ $json.deadline_at }} ({{ $json.deadline_hours }}h)\nReceived: {{ $json.received_at }}"
}
},
{
"id": "4",
"name": "Log to Postgres",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
400,
100
],
"parameters": {
"operation": "insert",
"schema": "public",
"table": "adtech_consent_incidents",
"dataMode": "autoMapInputData"
}
}
],
"connections": {
"Consent Event Webhook": {
"main": [
[
{
"node": "Classify Incident",
"type": "main",
"index": 0
}
]
]
},
"Classify Incident": {
"main": [
[
{
"node": "Slack #adtech-incidents",
"type": "main",
"index": 0
},
{
"node": "Log to Postgres",
"type": "main",
"index": 0
}
]
]
}
}
}
Workflow 5 — Weekly AdTech Compliance KPI Dashboard
Monday 8AM ET, emails CEO + DPO. Queries account database for:
- Accounts by tier and MRR
- Average IAB TCF 2.2 consent string valid percentage
- CCPA opt-outs processed in last 7 days
- Open GDPR DSARs
- COPPA under-13 flags in last 7 days
- FTC disclosure violations detected
A COPPA flag in the KPI report is not a metric to improve — it is a $51,744/violation FTC exposure item. The report surface makes that visible to the CEO every Monday.
{
"name": "Weekly AdTech Compliance KPI Dashboard",
"nodes": [
{
"id": "1",
"name": "Monday 8AM ET",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
0,
0
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 13 * * 1"
}
]
}
}
},
{
"id": "2",
"name": "Query KPI Data",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
200,
0
],
"parameters": {
"operation": "executeQuery",
"query": "SELECT tier, COUNT(*) as accounts, SUM(mrr_usd) as mrr, SUM(tcf_valid_consent_pct) / COUNT(*) as avg_tcf_valid_pct, SUM(ccpa_opt_outs_7d) as ccpa_opt_outs, SUM(gdpr_dsars_open) as open_dsars, SUM(coppa_flags_7d) as coppa_flags, SUM(ftc_disclosure_violations_7d) as ftc_violations FROM adtech_accounts GROUP BY tier ORDER BY mrr DESC"
}
},
{
"id": "3",
"name": "Build KPI Report",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
0
],
"parameters": {
"jsCode": "const rows = $input.all().map(i => i.json);\nconst totalMRR = rows.reduce((s, r) => s + (r.mrr || 0), 0);\nconst totalAccounts = rows.reduce((s, r) => s + (r.accounts || 0), 0);\nconst totalCCPAOptOuts = rows.reduce((s, r) => s + (r.ccpa_opt_outs || 0), 0);\nconst openDSARs = rows.reduce((s, r) => s + (r.open_dsars || 0), 0);\nconst coppaFlags = rows.reduce((s, r) => s + (r.coppa_flags || 0), 0);\nconst ftcViolations = rows.reduce((s, r) => s + (r.ftc_violations || 0), 0);\n\nlet tierBreakdown = rows.map(r =>\n `${r.tier}: ${r.accounts} accounts | MRR $${(r.mrr||0).toLocaleString()} | TCF valid ${(r.avg_tcf_valid_pct||0).toFixed(1)}% | CCPA opt-outs ${r.ccpa_opt_outs||0} | COPPA flags ${r.coppa_flags||0}`\n).join('\\n');\n\nconst body = `Weekly AdTech Compliance KPI \u2014 ${new Date().toISOString().slice(0,10)}\n\nTOTAL: ${totalAccounts} accounts | MRR $${totalMRR.toLocaleString()}\nCCPA opt-outs this week: ${totalCCPAOptOuts}\nOpen GDPR DSARs: ${openDSARs}\nCOPPA flags: ${coppaFlags}\nFTC disclosure violations: ${ftcViolations}\n\nBy Tier:\n${tierBreakdown}\n\nCritical compliance reminders:\n- IAB TCF 2.2: invalid consent strings in bid requests = GDPR Art.6 failure \u2014 check TCF valid % above\n- CCPA 15 biz day opt-out clock: any CCPA_OPT_OUT_OF_SALE events this week? Check incident log\n- COPPA: ${coppaFlags} under-13 flags this week \u2014 each is potential $51,744/violation FTC exposure\n- GDPR open DSARs: ${openDSARs} open \u2014 30-day deadline applies from receipt`;\n\nreturn [{ json: { report: body } }];"
}
},
{
"id": "4",
"name": "Email CEO + DPO",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
600,
0
],
"parameters": {
"operation": "send",
"sendTo": "={{ $vars.CEO_EMAIL }}",
"subject": "Weekly AdTech Compliance KPI \u2014 {{ $now.format('YYYY-MM-DD') }}",
"message": "<pre>{{ $json.report }}</pre>",
"additionalFields": {
"ccList": "={{ $vars.DPO_EMAIL }}",
"isHtml": true
}
}
}
],
"connections": {
"Monday 8AM ET": {
"main": [
[
{
"node": "Query KPI Data",
"type": "main",
"index": 0
}
]
]
},
"Query KPI Data": {
"main": [
[
{
"node": "Build KPI Report",
"type": "main",
"index": 0
}
]
]
},
"Build KPI Report": {
"main": [
[
{
"node": "Email CEO + DPO",
"type": "main",
"index": 0
}
]
]
}
}
}
The Architectural Problem in AdTech Consent Infrastructure
Cloud iPaaS automation pipelines create a specific consent compliance risk for AdTech platforms: the consent record is on the vendor's infrastructure, and the vendor's retention policy governs how long the record exists.
Under GDPR Art.7(1), the controller must be able to demonstrate that the data subject consented. If the consent record is in a cloud automation vendor's log — with a 90-day retention policy — and enforcement comes 18 months after collection, the consent record no longer exists. The burden of proof under Art.7(1) shifts to the controller, and 'the vendor deleted it' is not a valid defense.
The same issue applies to CCPA opt-out receipts. If a GPC signal was received by your cloud automation pipeline and the vendor log purged it, you cannot prove the 15-day clock started when it did — or that you honored it.
Self-hosted n8n keeps all consent records, timestamps, and processing logs under your infrastructure with your retention policy. The consent audit trail is yours, not your vendor's.
Four self-hosting arguments specific to AdTech:
- GDPR Art.7(1) consent demonstration: Consent records on vendor infrastructure with vendor retention policy — not under your control
- CCPA GPC signal receipt timestamp: Cloud automation vendor log is the only record of when GPC was received — becomes your legal timestamp
- COPPA 'knowingly' standard: Content classification pipeline logs on vendor infra = vendor timestamps are the FTC's evidence of when you had constructive knowledge
- IAB TCF 2.2 consent string audit: TCF invalid string events in vendor logs — your partner dispute evidence is subject to vendor retention policy
Get All 5 Workflows + the Full AdTech Compliance Bundle
All 5 workflow JSON files are available individually or as part of the FlowKit n8n Automation Templates bundle.
Individual templates: $12–$29 each at stripeai.gumroad.com
Full bundle (15 templates): $97 at stripeai.gumroad.com
Each template includes the complete n8n workflow JSON, a setup guide, and configuration notes for the compliance-specific parameters (TCF CMP endpoint, CCPA opt-out webhook URL, GDPR consent vault connection, COPPA age classification API).
Top comments (0)