Why we put the orchestrator in Craft Commerce, not Salesforce

Narration

This audio was generated with our Content Narration for Strapi plugin using ElevenLabs AI.
0:00 0:00

A healthcare training organization sold four different things through one website. Physical products, digital product licenses, paid events, and free event registrations. All of it had to be recorded in Salesforce, and the digital course purchases had to instantly unlock access in Thinkific LMS.

Three systems, four purchase types, one moment of truth: when the customer clicked buy, every system needed to agree on what just happened.

The default architecture choice would have put Salesforce in the middle. It is the system of record, it owns the business data, and the rest of the stack treats it as authoritative. Most agencies build it that way without thinking about it.

We chose the opposite. Craft Commerce orchestrated the entire flow. Salesforce was the source of truth, but it was not the control plane.

This Insight is the reasoning behind that decision, and what it took to make it hold up across six years of business change (via Solspace Inc.).

The 6-year engagement at a glance

Year continuous retainer
Systems integrated
Purchase types unified
Data types kept in sync

Salesforce was the source of truth. Craft was the origin and the orchestrator.

Before deciding where the orchestrator should live, we had to answer two questions that often get conflated: where does data originate, and where does it officially live?

For Centering Healthcare, the answers were not the same system, and that was deliberate.

Salesforce was the single source of truth for the business. Once data landed there, it was authoritative. Reporting, finance, customer service, leadership decisions, all anchored in Salesforce.

But most of the data that ended up in Salesforce did not originate there.

DataOriginates inSource of truth
Orders and customersCraft CommerceSalesforce
Course enrollmentsCraft CommerceSalesforce
Event registrationsCraft CommerceSalesforce
Stock and pricesSalesforceSalesforce

This split, origin separate from source of truth, is the part most integration projects collapse. They pick one system to be both, then spend the next two years patching the cases where the chosen system was not actually present at the moment the data was created.

Keeping origin and source of truth separate is harder to design but easier to live with. The system that creates the data does not have to also be the official record. It just has to make sure the official record gets updated correctly.


Why Craft, not Salesforce, was the orchestrator

The orchestrator question was now narrower: which system should be in charge of making sure Salesforce got the right data at the right time, and triggering downstream effects like Thinkific enrollments at the same moment?

The honest answer was Craft. Not because Craft owned the data, Salesforce did, but because Craft was the only system present at the moment the data came into existence.

Craft was the only system that saw all four purchase types. Physical products bought by individuals. Digital licenses bought by organizations to distribute internally. Paid event registrations with seat allocation. Free event signups for marketing. Salesforce got each of those as a clean record after the fact, but it never sat at the moment of the transaction.

If Salesforce had been the orchestrator, every customer-facing event would have needed a round trip: customer buys, Craft tells Salesforce, Salesforce decides what to do, Salesforce tells Craft and Thinkific. Two extra hops, two extra failure points, and the orchestration logic living in a system whose primary purpose is to be a CRM, not a workflow engine.

Putting the orchestrator in Craft meant:

  • One less hop for every customer-facing action
  • Orchestration logic written in the same codebase as the storefront, in PHP and reviewable in Git
  • Salesforce stays a clean record-keeper, which is the role it is actually good at
  • Failures in Salesforce never block a customer's purchase or course access

craft-salesforce-thinkific


Centering Connector: a custom Craft plugin, not an off-the-shelf integration

The orchestrator was a custom plugin we built and named Centering Connector. It is not a generic Salesforce plugin or an iPaaS connector. It is a plugin written for this client, this data shape, and this set of business rules.

That sounds like the expensive choice. In a 6-year engagement it was the cheap one.

Off-the-shelf connectors give you 80% of what you need on day one and then fight you for the remaining 20% forever. Custom plugins start at 100% fit and stay there as long as you keep maintaining them. When the client adds a new product type, a new field, a new business rule, and they will because that is what real businesses do, you change the plugin instead of finding workarounds for someone else's abstraction.

The plugin handled three jobs:

  1. Pulling stock and prices from Salesforce on a schedule. Batched, not real-time. Real-time sync sounds better in a sales meeting, but for stock and prices on a course catalog it adds risk without adding business value.
  2. Pushing orders, customers, and registrations to Salesforce after checkout. Idempotent, with a tracking key in Craft for every record, so a retry never created a duplicate in Salesforce.
  3. Pushing course enrollments to Thinkific the moment the order completed. No human in the loop, no support ticket, no "your access will be enabled within 24 hours" email.

YAML field mapping: making the integration partly client-owned

The detail we are most proud of is also the one that does not show up in any architecture diagram.

Every field mapping (products, users, orders, product types, custom Salesforce fields) lived in a YAML configuration file inside the plugin. Adding a new field, renaming a Salesforce field after the client's CRM team relabeled it, mapping a new product type the marketing team invented: all of it was a configuration change, not a code change.

This had a quiet but compounding effect: the client's head of IT could make small changes without us.

When they added a new product type or a new descriptive field on both systems, they updated the YAML and committed it. We reviewed at our pace. Their team kept moving at theirs. A class of "small request, big bottleneck" tickets that would have lived in our queue for weeks was simply not a category of ticket anymore.

We do this on purpose. We want our clients to be more independent on the small stuff so they can come to us with the harder problems. That is what justifies a 6-year retainer at a price the client keeps signing off on.


How we caught problems before the client did

A 6-year integration sees every kind of failure. The thing that mattered most was not preventing every failure, it was catching them fast enough that the client never noticed.

We logged extensively. Every sync run, every record processed, every mapping applied. Most of those logs were noise on a normal day. On a not-normal day they were the difference between "we already fixed it" and "the CFO is on the phone."

The recurring not-normal day was a silent change inside Salesforce. Someone on the client's CRM team would rename a field, change a picklist value, or repurpose a custom object. Nothing dramatic from their side, just admin work. From the integration's side, a previously-working mapping would start failing on specific records.

The logs caught these in hours. Without them, the integration would have looked unreliable. With them, the integration looked precise and the underlying CRM change was visible, which often led to a better conversation with the client about how to plan the next change together.


What this 6-year engagement is really proof of

Centering Healthcare is not the most technically extreme integration we have built. There are projects with more products, more systems, more traffic.

The point is that the architecture choices in year one were still right in year six. The orchestrator stayed in Craft. The origin-vs-source-of-truth split held. The YAML config kept absorbing business change. The custom plugin, written for this client's specific shape, kept fitting that shape as the shape itself moved.

When we say the connection is the product, this is the kind of connection we mean. Not a one-time integration project, but a control plane the business can keep running on.

Author

Need Similar Solutions?

If you're facing similar challenges or want to explore how I can help with your project, let's talk.

Get in Touch

Used technologies

Weekly Newsletter

Subscribe for monthly, practical AI demos designed to cut friction and boost real results for marketing, sales, and operations leaders.