Clear path for syncing companies and contacts from/to a CRM (maybe through a middleware)

As discussed in today’s DACH online meetup:

The most common case is somewhat like
“I want to have all my CRM contacts and companies in Mautic.”
with many add-ons like Mautic information like Newsletter subscription, DOI or Opt-out, or even behavior being piped back to the CRM.

As of today, many people have to implement that but all need to reinvent the wheel, frequently with rather ugly workarounds.

An approach would be:

  1. Create a clearer picture of possible requirements
  2. Define a feature set for generic implementation within Mautic (should cover the basic needs
  3. Provide guidelines for more flexible and more sophisticated connections through middleware e.g. n8n

For the records: specific thoughts and statements from today’s meetup

  • Synchronization must accurately reflect existing CRM data in the marketing system (no independent data logic in MA). Ability to map flat datasets (including company data) into relational structures. Ability to associate a contact with multiple companies
  • Support mapping between external IDs and internal system IDs (e.g. Mautic ID)
  • Advanced company matching logic beyond simple name matching (e.g. additional attributes)
  • Support for custom matching strategies (e.g. combined fields like name + postal code)
  • Data normalization before matching (e.g. lowercase, remove special characters)
  • Duplicate handling must be flexible and configurable
  • Support integration with existing Golden Record / master data systems as the source of truth
  • Support complex company structures (e.g. groups, subsidiaries, hierarchical relationships)
  • Handle company renaming without causing inconsistencies or data loss
  • Prevent incorrect assignments caused by ambiguous or duplicate company names
  • Provide conflict resolution strategies for inconsistent data (e.g. CRM vs form input)
  • Support bidirectional data flows (e.g. sending enriched data back to CRM)
  • Keep complex logic transparent and maintainable (e.g. via visual middleware tools)

Oh boy, I’ve conceptualized and implemented this partially with N8n (+Redis) as processing queue and Directus as CRM.

  1. Mapping form fields to contact attributes is not allowed, instead use webhooks for form submissions
  2. Every event gets enqueued in N8n and forwarded to other N8n Workflowa and/or to the contacts event log in directus.
  3. Directus is responsible for performing changes or rejects the event.
  4. On contact change Directus sends a change request to the N8n queue which in turn updates the contact in Mautic.

Boundaries:

  • N8n partitions the entities (in this case the contact) so events are processed in order and only processed ones.
  • One Redis atomic Increment to make sure an event is only processed ones
  • One Redis list per partition is used to process events in order
  • Mautic and Directus both hold a contact version number
  • Mautic users are not allowed to change the values of contact attributes from within Mautic
  • I am using N8n data tables as a temporary event processing store. A external database could be used in case the 50mb storage is not enough.

While this is not a pure middleware solution, I think that’s as close as it can get. We need to make sure that the contact doesn’t get corrupted and thus need optimistic locking in the CRM. That’s why some custom code is needed in there.

The processing queue in N8n is quite generic and can plug and play subflows for distinct entities

Not sure this is the complete answer. This topic has been debated in CRM design for years, and in my view the underlying data model is the real issue.

  • A “contact” is usually not just a person, but a person in a specific company context. In practice, contact details (email, phone, role) often differ per company. That’s why we model them as separate contacts today, even if they represent the same human (optionally linked via a custom field).
    → Properly speaking, this points to a missing Person layer above Contact, rather than a need for multi-company contacts.
  • The actual use case (one person actively working with multiple companies at the same time) exists, but it’s relatively rare and typically limited to roles like consultants, advisors, or investors.
  • From a marketing automation perspective, this introduces ambiguity:
    • Activities, scoring, and campaign logic are tied to the contact
    • If one contact is linked to multiple companies, which company does the behavior belong to?
    • This leads to unclear segmentation, unreliable reporting, and potentially incorrect campaign triggers
  • Commercial processes are usually unambiguous:
    → A deal is tied to exactly one company
    This reinforces the idea that the contact context should also be clearly scoped.
  • There is also a product risk:
    • A feature that solves edge cases can introduce data integrity issues for the majority
    • Accidental multi-assignment, unclear ownership, and broken automations are likely side effects
  • In our setup, we address related scenarios differently:
    → We distinguish between current and former company relationships, instead of allowing multiple active ones
    This adds a time dimension without breaking the core model.

Conclusion:
The requirement is valid in edge cases, but adding multi-company associations at the contact level may create more problems than it solves. A cleaner approach would be to introduce a proper Person–Contact separation, rather than overloading the contact entity itself.