Case study · Automation & integration
Holos33 had working forms, a configured Zoho CRM and an email system that sent reliably. Everything looked fine. When we started measuring, 985 of 1,136 submissions carried the wrong origin label. Filter out the spam flood and two thirds of genuine traffic was going to the wrong destination. One form had also been rejecting every single submission for 25 days — without one error reaching anyone. Here is what AIAgentCycle found, what we fixed, and — more importantly — how we made it provable. Not with a report, but with a chain that re-tests itself every day.
About this case. Holos33 is our own platform. We publish this case because we test everything on ourselves first and because the figures are measured, not estimated. External cases will follow; the first one is in preparation.
-
985
of 1,136 submissions carried the wrong origin label
-
100%
of the pricing form silently rejected
-
0
error alerts had ever been delivered
-
21/32
of genuine traffic was being misrouted
On this page: what was delivered · the problem in numbers · a two-sided gate approach · the architecture · forms into Zoho CRM · bookings · email and GDPR · failure handling · anti-spam and Cloudflare · server hardening and Zero Trust · monitoring · results · what we build for you · frequently asked questions
The case in one paragraph
AIAgentCycle measured, repaired and instrumented the full chain from web form to CRM, booking system and mailing list for privacy-first wellbeing platform Holos33. The chain runs from four active Fluent Forms forms across ten pages of a WordPress site, through a PHP bridge and a self-hosted n8n workflow, into Zoho CRM, Zoho Bookings and Listmonk. We found three causes of silent loss — a routing bug in PHP, an anti-spam filter that never received its own input, and an n8n chain that let session attribution override page context — plus an alerting system that had never once fired. Afterwards six of the seven destinations were demonstrated end-to-end with real browser submissions — the seventh, a standalone newsletter list, has no reachable form and was tested synthetically. A daily check now verifies that it stays that way.
What AIAgentCycle delivered
One continuous chain, from click to list, with proof at every handover. Delivered and running in production:
| Delivered | What it does |
|---|---|
| Form-to-CRM integration | Four forms across ten pages in two languages, each writing the correct origin, segment and language preference as structured fields in Zoho CRM |
| Single-source origin | One function determines origin from the post ID; the rest of the chain only carries it. Translated copy can no longer break routing |
| Idempotent delivery | Zoho upsert on email and Listmonk PATCH/POST, so a retry never produces a duplicate lead |
| Queue with a safety net | Four delivery attempts, a 60/300/900-second ladder, a dead-letter queue with payload, and a daily alarm |
| Layered timeout budget | Four increasing limits (5 · 25 · 45 · 60 s) so any failure is caught inside the chain instead of disappearing outside it |
| Booking flow | Straight from form to the right conversation type in Zoho Bookings, with the lead already in the CRM |
| Email and GDPR | Eight target lists in Listmonk, double opt-in in the right language, retention per log, and no mailing without confirmed consent |
| Anti-spam and access | Cloudflare IP Access Rules, a WAF rule, Turnstile prepared, and Zero Trust Access in front of the automation environment |
| Error handling | Error handler wired up and proven with a controlled failure — the alarm that existed but had never once fired |
| Three daily watchdogs | Each positively and negatively tested, so a watchdog reporting nothing is demonstrably watching rather than silent |
| Release discipline | Staging, a promotion procedure, SHA-256 before and after, a rollback point per change, and a readable trail of every intervention |
About Holos33
Holos33 is a privacy-first wellbeing platform by Good Nature Vibe B.V., offering an AI coach, biofeedback and modules for individuals, teams and research partners. It serves four distinct audiences — consumers, companies, professionals such as coaches and therapists, and academic research partners — each with its own form, its own follow-up and its own mailing list. An early-access programme runs alongside it via the Holos33 early-access page.
Those four audiences are exactly what makes this case instructive: the moment one enquiry lands on the wrong list, a researcher receives a sales email and a procurement manager receives a research invitation. The system is technically working, and commercially doing damage.
The complete workflow: from webhook receipt to confirmation email, with idempotent writes into Zoho CRM and Listmonk.
What we found
The brief was a single sentence from the owner: “the forms don’t work, people don’t end up on the right list.” That turned out to be not one problem but four independent ones — which were masking each other.
1. One forgotten line that affected 985 records
The PHP bridge that forwards form submissions did recognise the subject “Business partnership”, but that branch only set the CRM field and forgot the origin. As a result, 985 of 1,136 submissions arrived labelled “General contact” instead of their actual segment. No error, no log line — the data was complete, only the label was wrong.
2. An anti-spam filter that never received its own input
The pricing form carried a custom anti-spam check using three hidden fields. Fluent Forms, however, filters incoming fields against the form definition (array_intersect_key), and those three fields were not part of it. They were discarded before the check ran. The check then concluded “no evidence of a real visitor” and rejected everyone, for 25 days, with a red error message and without storing anything at all.
Why this went unnoticed for weeks: the guard had been tested with hand-built data in which the fields were present. The test proved the read routine worked and skipped the data pipeline entirely. Of seventeen log entries, nine were tests and seven were ours — leaving exactly one real visitor who had been turned away.
3. Routing on session attribution instead of page context
The n8n workflow re-derived the origin from the source_url and landing_page fields. Those are attribution fields: they record where a visitor entered the site, not where they filled in the form. Anyone landing on the business page and then completing the research form was classified as “Business” — overwriting the correct value PHP had supplied. Of 32 genuine submissions, 21 had a landing page different from the form page: two thirds of real traffic.
4. A spam flood that made the numbers unreadable
Around 1,117 of 1,136 submissions came from a single small IP range (80.94.95.0/24). Those bots went straight to the contact form, so for them the landing page was the form page. That made the routing bug look like an edge case: 25 deviations out of 1,215 submissions. Only after separating real traffic from spam did the true picture appear.
The lesson that shaped the whole engagement: a count of zero tells you nothing until you know the denominator. “No more spam” and “no more submissions” both produce zero. Every check in this case is therefore two-sided: it must be able to pass and to fail, and both have been demonstrated.
The approach: measure first, repair second
We changed nothing before the baseline was in place. The order was fixed, and each step had a gate that had to close from both sides before the next one started.
- Audit and baseline. Every submission, execution, list and log line counted and dated, with a backup and rollback point per system.
- Gate 0 — does legitimate traffic still get through? Not inferred from “no more spam”, but proven with a real browser submission that demonstrably arrived in n8n.
- Gate 1 — is delivery airtight? Including retries and a dead-letter queue with an alarm.
- Phase 3a — routing in PHP. Stable keys instead of label text, plus page context based on post ID.
- Gate 2 — the broad test. One real browser submission per destination, at least two of them with a landing page deliberately different from the form page.
- Phase 3b — routing in n8n. Remove the duplicate derivation, leaving a single source of truth.
- Gate 3 — the negative test. Deliberately cause a failure and prove the safety net fills and alerts.
- Phase 4 — no more silent fallback. Only once everything above is proven.
Why that order mattered: during the broad test, a change the API reported as applied turned out not to be running in production at all — n8n separates the working copy from the published version. Three of four narrow tests were green. Only the test in which the old code would give a different answer than the new one exposed it. A narrow gate would have reported success on a change that was never deployed.
The broad gate: one real submission per destination, each read back on origin, segment and target list.
The architecture
The chain has four links and one rule: every fact has exactly one source.
| Link | Role | What we did |
|---|---|---|
| WordPress + Fluent Forms | Four active forms across ten pages, in two languages | Stable keys per option, page context from post ID, origin determined in a single function |
| PHP bridge + Action Scheduler | Queues and delivers the submission | Retry ladder, dead-letter with retention, timeouts that increase from the inside out |
| n8n (self-hosted) | Normalises, enriches and writes | Duplicate derivation removed, idempotent writes, error handling actually connected |
| Zoho CRM · Zoho Bookings · Listmonk | Destination | Upsert on email, eight target lists, double opt-in in the right language |
Connecting forms to Zoho CRM
Every submission is normalised into one fixed shape and then written using an upsert keyed on email address. That makes delivery idempotent: if the same submission arrives twice through a retry, no duplicate lead is created — the existing one is updated. Without that property, any retry strategy is a duplicate factory.
Origin is determined in exactly one place — in PHP, from the actual post ID of the page carrying the form — and carried through the rest of the chain. Where the label text of an option used to drive routing, a stable key now does. As a result, copy can be translated or rewritten without anything breaking. That was not a theoretical risk: of eight subject options, six had already been translated, and the two the routing depended on were precisely the ones still outstanding.
The routing table: eight origins, each with its segment and target list, defined in one place rather than scattered across the chain.
A created lead in Zoho CRM, with origin, segment and language preference as structured fields rather than free text.
Bookings: from form to calendar
A demo request does not need to land in an inbox. After submitting, the requester is taken straight to Zoho Bookings, where they pick a slot for the right conversation type — business demo, professional intake, or research introduction. By that point the lead is already in the CRM with the correct origin, so the meeting starts with context instead of a questionnaire.
Routed straight to the right conversation type, with the lead already in the CRM.
Email, double opt-in and GDPR
Listmonk is the self-hosted email platform in this chain. Eight target lists in total: one per segment, plus a separate newsletter list per language. Anyone signing up receives a double opt-in in their own language, and only a confirmed opt-in counts as consent.
At the start, the confirmation page was English, unbranded, and displayed the words “Private list” to Dutch visitors. That is exactly the moment at which someone decides whether to trust you. It is now localised, branded and consistent with the rest of the platform.
One rule we made explicit: never run a mailing against an error or rejection log. Those addresses by definition have no confirmed opt-in — the confirmation step is precisely what did not happen. The rejection log therefore stores only the address, no content, for thirty days; the dead-letter stores the full submission for ninety days, because its purpose is to recover a real lead.
Eight target lists with their counts. Two of them received their first correctly routed sign-up during this engagement.
Failure handling: what happens when something breaks
A chain that only works when everything cooperates is not a chain, it is luck. Failure handling is therefore layered, from the inside out, and every layer cuts off earlier than the one outside it:
| Layer | Limit | What happens when exceeded |
|---|---|---|
| Individual API call in n8n | 5 seconds | Aborts; three retries inside the workflow |
| The whole workflow | 25 seconds | Workflow cancelled, HTTP error returned |
| The call from WordPress | 45 seconds | Delivery counts as failed |
| The PHP process | 60 seconds | Hard limit; never reached first |
If a delivery fails, a retry ladder of 60, 300 and 900 seconds follows. If all four attempts fail, the submission goes to the dead-letter — with its payload, so the lead can be recovered — and the daily check raises an alarm. If a retry does succeed, that is logged separately without personal data, as a warning rather than an outage.
Why that last part exists: an attempt that fails and then succeeds on retry previously left only a line in the debug log. If the integration were to reject every first attempt systematically, everything would still work, the dead-letter would stay empty, and nobody would know. A safety net that only watches the terminus misses the approach.
The safety net that had never worked
The monitoring workflow was correctly configured as the error handler for every other workflow. Yet not a single alert had ever been sent. The reason: the workflow was missing the node that responds to errors, and the alert step it did contain was connected to nothing. The intended design was documented inside the workflow itself; only the wiring was absent. Once connected, it fired for the first time in its existence on the very next controlled failure.
Dead-letter with retention, a retry log without personal data, and the daily summary that watches both.
Anti-spam without blocking real visitors
The spam flood originated from one small IP range, which made it precisely targetable: Cloudflare IP Access Rules and a WAF rule. A Turnstile widget has been created and is ready for the forms; it goes live once the keys are in place. That is the easy half.
The hard half is proving you have not locked out customers in the process. Every anti-spam measure is therefore built fail-open: if the input a check depends on is missing, it does not reject — it records that the input was missing. Missing input is a bug on our side, not evidence against the visitor. That exact inversion was the cause of the 25 days of silent rejection.
Targeted blocking of the range the flood came from, with a two-sided check that legitimate traffic still passes.
Server hardening and Cloudflare Zero Trust
The automation environment now sits behind Cloudflare Zero Trust Access: the n8n instance is no longer reachable with a password alone, but behind an access policy that decides who gets in before the application answers. For an automation platform that matters more than for a website, because it holds credentials for the CRM, email and booking systems.
Also implemented on the environment:
- Separated staging and production with a promotion procedure: lint, copy, set ownership, purge cache, smoke test — and only then live.
- A rollback point per change, with SHA-256 before and after plus a full database dump. One dump failed silently because the executing user lacked write permission on the target path; since then, backups are validated on file size before they count as valid.
- Credentials only in permission-restricted files, never in documents, chats or workflow definitions.
- Retention on every log: 90 days for the dead-letter with content, 30 days for the rejection log holding only an address, 14 days for the retry log with no personal data.
- Timeouts that match the actual runtime — delivery turned out to run in the web context with a 30-second limit, while the measurement had been taken on the command line where it was unlimited. Without that correction, a slow delivery would abort fatally and skip the safety net entirely.
Cloudflare Zero Trust in front of the automation environment: access is evaluated before the application responds at all.
Monitoring: watchdogs that can fail
Three checks now run daily to re-verify what was delivered: is spam still blocked from the offending range and is legitimate traffic still getting through; is delivery airtight and the dead-letter empty; and is routing still correct for every destination in both languages.
Every watchdog has been negatively tested. That means we deliberately gave it a situation that is wrong and confirmed it actually turns red. One of our own watchdogs passed on zero measurements in its first version — a fatal error in the read routine was swallowed by error suppression, after which the script concluded “found nothing, so nothing is wrong”. That is the same reasoning error as “no more spam, so it works”, and the negative test is the only thing that catches it.
Three checks, each with a positive and a negative test, reported in the daily summary.
The results
| Area | Before | After |
|---|---|---|
| Submission routing | 985 of 1,136 on the wrong list | Six of seven destinations proven end-to-end with real browser submissions; the seventh synthetically |
| Pricing form | 100% rejected for 25 days, nothing stored | Working; its target list received its first sign-up |
| Origin determination | Two sources that diverged | One source: the page’s post ID |
| Translation sensitivity | Routing depended on label text | Stable keys; copy can be translated freely |
| Failed delivery | Invisible; no retry, no alarm | Four attempts, dead-letter with payload, daily alarm |
| Error alerts | Never one delivered | Error handler connected and proven with a controlled failure |
| Access to the automation layer | Password | Cloudflare Zero Trust Access |
| Verifiability | Assumptions | Three daily watchdogs, each negatively tested |
Why our method finds what a code review misses: our first diagnosis of the cause was wrong. Our first estimate of the impact was too high. Our first timeout figures would have produced a false alarm. And one change turned out not to be running after we published it. Each of those four was caught by a test, not by reading documentation. That is not a weakness of the approach — it is the approach: we assume our own assumption can be wrong and build the test that proves it. A supplier who tells you a flawless story usually never ran that test.
What this means for your organisation
This case is not about Holos33. It is about a pattern we see in almost every integrated environment: the system reports nothing, so everyone assumes nothing is wrong. Silent failures have no complaining user. They only have revenue that is lower than it should be, with nobody able to point at why.
Three questions you can ask yourself today:
- Can you point to where your last ten enquiries ended up? Not “in the CRM”, but on which list, with which origin.
- What happens if the integration is down for ten minutes? If the answer is “I don’t know”, the answer is probably “that enquiry is gone”.
- When did your error alert last fire? Never is not a good sign — it usually means it was never wired up.
What AIAgentCycle builds for you
We connect systems that each work on their own but together prove nothing. Forms, CRM, email, calendars, invoicing, inventory, customer portals — and anything with an API. The technology is rarely the problem; the verifiability is.
What we are made of
- Workflow automation with n8n, self-hosted in your own environment, so your customer data never leaves your infrastructure and the logic stays readable instead of buried in a SaaS product.
- CRM integrations — Zoho, HubSpot, Pipedrive, Dynamics — with idempotent writes, so retries never create duplicate records.
- AI agents that do something rather than say something: enriching, classifying, routing and summarising inside a chain you can audit.
- Back-office and administrative automation: quotes, orders, invoices and document flows between systems that do not talk to each other.
- Server hardening and Cloudflare Zero Trust, including separated staging, promotion procedures and a rollback point per change.
- Verifiability as a deliverable: every integration ships with a watchdog that can fail, and a negative test proving that it does.
What sets us apart, in one sentence: most suppliers deliver a working integration. We deliver a working integration, plus the proof that it works, plus the alarm that fires on the day it stops.
How we work
- Baseline. We count first: how many enquiries came in, how many are in your systems, and where those numbers diverge.
- Diagnosis with proof. No hunches — a reproduction. We show you the failure before we repair it.
- Repair behind gates. Every step has a check that must close from both sides, and a rollback point before anything changes.
- Demonstrate. Real submissions through the real chain, read back all the way into the target list.
- Hand over. Watchdogs, retention periods, alerting and a readable trail of what was done and how to undo it.
Frequently asked questions
What does it cost to connect a form to a CRM?
That depends less on the integration than on everything around it. One form into one CRM field is a matter of hours. What takes time is making it provable: retries, a safety net, origin from a single source, and checks that are able to fail. In this case most of the effort went not into the integration but into measuring, proving and monitoring.
Why self-hosted n8n rather than an off-the-shelf connector?
Because the logic does not fit on one line. Four active forms, ten pages, two languages, eight destinations and a booking system is not an “if this then that”. n8n is a workflow automation platform you can run yourself, which means the data never leaves your environment and the logic can be read rather than trusted.
How do I know whether my forms are losing leads?
Compare three counts over the same period: submissions in your form plugin, records created in your CRM, and sign-ups on your mailing list. If they diverge, something is disappearing between two links. If they match, check whether the origin is correct — that is the failure that produces no difference in the counts at all.
What is a dead-letter queue and why do I need one?
A dead-letter queue holds a delivery that still has not arrived after every retry, including its full content. Without one, a failed delivery is gone for good. With one, it is a five-minute manual action. That difference is precisely the difference between a lost customer and a late reply.
Is this GDPR compliant?
The chain is built so that consent counts only after a confirmed double opt-in, every log has a retention period, the retry log holds no personal data, and no mailing is ever run against addresses that never completed confirmation. That is a technical implementation, not legal advice — always have your lawful basis and processing register reviewed by your own counsel.
Does this work with HubSpot, Pipedrive or Microsoft Dynamics?
Yes. The destination is the easiest link to swap. The hard parts — origin from a single source, idempotent writes, retries with a safety net, and checks that can fail — are not CRM-specific.
Start with the baseline
We never start by building. We start by counting: how many enquiries came in, how many are in your CRM, and which list they are on. We make that gap visible in half a day.
What you get:
- A side-by-side count of your forms, CRM and mailing list over the same period
- A reproduction of every gap we find — the failure demonstrated, not assumed
- A remediation plan with sequence, risk and rollback per step, even if you execute it yourself
Tell us which of your forms you would like measured.
Engagement delivered by AIAgentCycle for Holos33, a brand of Good Nature Vibe B.V., August–September 2026. Holos33 and AIAgentCycle are trade names of the same company, Good Nature Vibe B.V.; this engagement followed the same method, gate checks and documentation discipline as external work. All figures quoted are measured values from the systems involved. Stack: WordPress, Fluent Forms, WPML, PHP, Action Scheduler, n8n (self-hosted), Zoho CRM, Zoho Bookings, Listmonk, Cloudflare (WAF, Turnstile, Zero Trust Access).