Rebuilding GDPR Consent as Country-Tiered Workflows
A country-blind consent gate would have gone live undetected if an adversarial QA pass had not caught it. The first build marked any contact marketable on double opt-in alone, with no check on country. We rebuilt roughly fourteen legacy campaigns as five HubSpot workflows and five country-cohort lists, keyed on a Legal-approved CSV, then closed that gap with a cohort re-check before the corrected version went into the sandbox.
Executive Summary
Context
The same global enterprise SaaS company anchoring its marketing operations to a new HubSpot instance sold into North America, EMEA and APAC under GDPR. Any consent rebuild had to preserve the country-level distinction its Legal team had already approved, not collapse it into one global opt-in flag.
What We Built
We built five HubSpot workflows and five country-cohort lists driven by a Legal-approved CSV, replacing a single global opt-in flag with a country-aware consent state machine. It gates marketable status, times a region-specific confirmation send, and wipes the consent record on unsubscribe.
Tech Stack
- HubSpot
- Salesforce
Not a fit if your consent obligations are uniform across every market you sell into, since the country-cohort design exists to enforce different rules per region. It also assumes your Legal team can produce and maintain a country-tier mapping, and that an adversarial QA pass happens before go-live rather than after.
The Challenge
The legacy platform enforced GDPR consent through roughly fourteen separate country-specific campaigns, each carrying its own opt-in, double opt-in and unsubscribe logic approved by Legal over years of accretion. Collapsing that into a single HubSpot opt-in flag would have erased the country distinction Legal required. The rebuild had to preserve per-country logic on a platform with no native concept of a country-tiered consent state.
Our Approach
Five workflows replace the fourteen legacy campaigns, each keyed on country-cohort list membership rather than logic written into the workflow itself. WF-1 runs on a country or customer-status change. WF-2 fires when opt_in becomes true, WF-3 when double_opt_in becomes true, WF-4 when unsubscribed becomes true and wipes the consent record, and WF-5 when a custom double-opt-in flag becomes true. A Legal-supplied CSV compiles into cohorts.json, so re-tiering a country is a data change, not a workflow rewrite.
An adversarial QA pass against the first build found that WF-3 granted marketable status the moment double opt-in completed, with no check against the contact's own country cohort, a real compliance defect that could market to a country under a stricter consent tier than its record supported. The fix added a cohort-list re-check to WF-3, plus a 15-minute wait ahead of the DACH welcome send so that cohort clears the same gate as every other market. WF-5's bypass flag now auto-clears after seven days. The corrected build sits in the sandbox disabled and unenrolled, blocked only on delivery of the client's EN/DE confirmation and DACH welcome templates.
Impact
Country tier changes without a workflow rewrite
Cohort membership comes from a Legal-supplied CSV rather than hardcoded logic, so adding a country or correcting a misclassification is a data change to cohorts.json, not a rebuild of any of the five workflows.
A country-blind marketable status gap closed before go-live
WF-3 now re-checks a contact's country cohort before granting marketable status. The defect the QA pass caught, where double opt-in alone made any contact marketable, cannot recur once the workflow re-enables.
Unsubscribe fully wipes the consent record
WF-4 clears the consent record the moment a contact unsubscribes, rather than leaving a stale opt-in flag set alongside the unsubscribe status, which would otherwise read as contradictory consent state on audit.
A third-party bypass that cannot silently persist
WF-5's third-party bypass flag auto-clears after seven days, so a third-party-sourced exception to the standard consent flow carries a built-in expiry rather than depending on someone remembering to revoke it.
Five workflows replace the legacy campaign set: WF-1 triggers on a country or customer-status change, WF-2 on opt_in becoming true, WF-3 on double_opt_in becoming true, WF-4 on unsubscribed becoming true, and WF-5 on a custom double-opt-in flag becoming true. Each keys on country-cohort list membership rather than logic written into the workflow itself.
Country tiers come from a CSV the client's Legal team approves and supplies, compiled into cohorts.json and read by five country-cohort lists, ids 651 through 655. Re-tiering a country is a data update, not a change to any workflow's logic.
As first built, WF-3 granted marketable status on double_opt_in alone. An adversarial QA pass caught that a contact completing double opt-in became marketable regardless of country, and the fix added a cohort-list re-check to WF-3 before marketable status is granted.
WF-3 waits 15 minutes before sending the DACH welcome email, so the German and Austrian cohort clears the same consent gate as every other market rather than receiving it ahead of confirmation. WF-5's third-party bypass flag auto-clears after seven days rather than persisting indefinitely.
Legal input Workflows Gate & state Legal-approved CSV country-tier mapping cohorts.json compiled lookup Country-cohort lists ids 651-655 WF-1 country/status change WF-2 opt_in true WF-3 double_opt_in true WF-4 unsubscribed true WF-5 custom double opt-in true Cohort re-check corrected after QA catch Consent record marketable status CSV compiles in mechanism 6 feeds cohort lists mechanism 6 country/status change country/customer-status change (WF-1) opt_in true opt_in becomes true (WF-2) double_opt_in true double_opt_in becomes true (WF-3) unsubscribed true unsubscribed becomes true (WF-4, wipes the consent record) custom opt-in true custom_double_opt_in becomes true (WF-5) re-checks cohort WF-3 re-checks the same cohort lists before allowing marketable status no check (pre-fix) any contact completing double opt-in became marketable regardless of country grants marketable WF-3 re-checks the same cohort lists before allowing marketable status assigns cohort country/customer-status change (WF-1) records opt-in opt_in becomes true (WF-2) wipes record unsubscribed becomes true (WF-4, wipes the consent record) bypass, clears 7d WF-5 auto-clears the third-party bypass flag after 7 days
FAQ
A contact who completes double opt-in gets marked marketable without regard to which country's consent rules apply, a real compliance defect rather than a theoretical one. Catching it requires an adversarial QA pass that tests the workflow against every cohort, not just the default path; here that pass added a cohort-list re-check to the workflow before it grants marketable status.
A CSV compiled into a lookup file lets Legal own the country-tier mapping directly, and lets a re-tier or correction ship as a data change rather than a workflow edit. Here five country-cohort lists read the same compiled file, so all five workflows stay consistent without duplicating the logic five times over.